[카테고리:] AWS

  • Nginx: 마이크로캐싱(Micro-Caching) 적용하기

    Nginx: 마이크로캐싱(Micro-Caching) 적용하기

    마이크로 캐싱이란?

    마이크로 캐싱은 아주 짧은 TTL(보통 1~10초) 동안 응답을 캐시에 저장해 두고, 같은 요청이 들어오면 백엔드 대신 캐시에서 바로 응답하는 기법입니다. 짧은 TTL이라 실시간성은 유지하면서도, 순간 트래픽 폭주(새로고침, 인기 API 호출 등)를 효과적으로 흡수할 수 있습니다.

    필요한 이유

    • 사용자가 새로고침을 여러 번 하거나, 다수 유저가 동시에 동일 API를 호출하면 백엔드(DB, 애플리케이션)에 부하가 급증합니다.
    • 대부분의 API/페이지는 몇 초 단위로 변경되지 않기 때문에 짧게라도 캐시하면 부하를 크게 줄일 수 있습니다.

    ⚙️ 동작원리

    1. 첫 요청 → 캐시에 없음 → 백엔드 호출 → 응답 저장
    2. TTL(예: 3초) 안의 동일 요청 → 캐시에서 바로 응답
    3. TTL 만료 → 백엔드 재호출 후 캐시 갱신

    Nginx는 $upstream_cache_status 값으로 캐시 상태를 알려줍니다.

    $upstream_cache_status 값과 의미

    의미
    MISS캐시에 없음, 백엔드 호출
    HIT캐시에서 응답
    EXPIRED캐시 있었지만 TTL 만료, 백엔드 호출 후 갱신
    BYPASS캐시 우회 조건에 해당(Authorization, Cookie 등)
    STALETTL 지났지만 오래된 캐시로 응답(갱신 중)

    기본 설정 예시 (API)

    • /etc/nginx/nginx.conf ➡️ http{} 블록
    # 캐시 저장소
    proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:50m max_size=1g inactive=10m use_temp_path=off;
    
    # 인증 헤더 감지(개인화 요청은 캐시 제외)
    map $http_authorization $auth_cache_bypass {
        default 1;
        ""      0;
    }
    • server{} 블록
    # API만 마이크로 캐싱
    location ^~ /api/ {
        proxy_pass http://localhost:port;
    
        proxy_cache my_cache;
        proxy_cache_key "$scheme$host$request_uri";
        proxy_cache_valid 200 3s;          # TTL 3초
        proxy_cache_lock on;               # 동시 폭주 방지
        proxy_cache_use_stale updating;    # 갱신 중에는 이전 캐시 사용
    
        # 안전장치: 인증 요청/쿠키 발행 응답은 캐시 제외
        proxy_no_cache       $auth_cache_bypass $upstream_http_set_cookie;
        proxy_cache_bypass   $auth_cache_bypass $upstream_http_set_cookie;
    
        add_header X-Cache-Status $upstream_cache_status always;
    }

    🧱 테스트 방법

    # 첫 호출 → MISS
    curl -I https://example.com/api/data | grep -i x-cache-status
    
    # TTL 내 재호출 → HIT
    curl -I https://example.com/api/data | grep -i x-cache-status

    🚨 주의

    • 개인화 데이터(로그인 사용자별 데이터)는 절대 캐시하면 안 됨 → Authorization/Cookie 조건으로 캐시 우회
    • POST, PUT 요청은 Nginx 기본 설정상 캐시되지 않음
    • TTL이 너무 길면 데이터 최신성이 떨어지고, 너무 짧으면 효과가 적음 → 2~3초부터 시작해서 조정
    • 쿼리스트링이 다르면 별도 캐시로 저장되므로, 불필요한 랜덤 파라미터는 제거

    ⛺️ 확장: 정적 파일 + 마이크로 캐싱

    왜 정적 파일에도 마이크로 캐싱을 걸까?

    • 백엔드가 정적 파일(JS, CSS, 이미지 등)을 직접 서빙하는 경우, 많은 유저가 동시에 요청하면 백엔드 리소스를 불필요하게 소모합니다.
    • 특히 빌드 시 해시(app.abc123.js)가 붙은 파일은 변경 시 파일명이 바뀌므로 오래 캐시해도 안전합니다.
    • Nginx가 서버 앞단 캐시(프록시 캐시)로 한 번만 백엔드에 요청하게 하면, 다수의 요청을 빠르게 처리할 수 있습니다.

    🧱 설계 원칙

    1. 요청에 쿠키가 있어도 캐시 허용
      • 정적 파일에는 보통 개인화 데이터가 없음.
    2. 응답에 Set-Cookie가 있으면 캐시 금지
      • 혹시라도 백엔드가 정적 파일 응답에 세션 쿠키를 발행하는 경우 안전하게 우회.
    3. 브라우저 캐시도 함께 설정
      • 해시가 있는 파일은 1년 + immutable 권장.
    4. 서버 캐시 TTL은 짧게
      • 마이크로 캐싱 용도로 1분~10분 정도가 적당.


    ⚙️ Nginx 설정 예시

    # 정적 파일(해시 포함) + 마이크로 캐싱
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
        proxy_pass http://localhost:port;                # 백엔드 서빙 유지
    
        # --- 서버 앞단 캐시(Nginx 프록시 캐시) ---
        proxy_cache my_cache;
        proxy_cache_key "$scheme$host$request_uri";
        proxy_cache_valid 200 10m;                        # TTL: 10분 (해시 없는 파일은 더 짧게)
        proxy_cache_lock on;                              # 동시 폭주 방지
        proxy_cache_use_stale updating;
    
        # 요청 쿠키는 허용, 응답 Set-Cookie 시 캐시 제외
        proxy_no_cache       $auth_cache_bypass $upstream_http_set_cookie;
        proxy_cache_bypass   $auth_cache_bypass $upstream_http_set_cookie;
    
        # --- 브라우저 캐시 ---
        expires 1y;
        add_header Cache-Control "public, max-age=31536000, immutable" always;
    
        # 상태 확인용 헤더
        add_header X-Cache-Status $upstream_cache_status always;
    }

    ⚠️ 해시 없는 파일(예: /styles/main.css)이라면 proxy_cache_valid를 더 짧게(예: 1~5분) 두고, 브라우저 캐시도 max-age=300 정도로 조정하세요.


    🧱 테스트 방법

    # 첫 요청: MISS
    curl -I https://example.com/_next/static/chunks/app.abc123.js | grep -i x-cache-status
    
    # TTL 내 재요청: HIT
    curl -I https://example.com/_next/static/chunks/app.abc123.js | grep -i x-cache-status
    
    # 브라우저 캐시 헤더 확인
    curl -I https://example.com/_next/static/chunks/app.abc123.js | egrep -i 'cache-control|expires'

    🧤 운영 TIP

    • 정적 전용 서브도메인(예: static.example.com)을 사용하면 브라우저가 쿠키를 아예 붙이지 않아 캐시 효율 ↑.
    • 빌드 툴(Next.js, React, Vue 등)의 filename hashing을 켜두면 캐시 무효화 걱정 없이 TTL을 길게 가져갈 수 있음.
    • Nginx 프록시 캐시 + 브라우저 캐시를 동시에 쓰면 최초 1회만 백엔드 요청, 그 이후는 대부분 브라우저 또는 Nginx에서 응답.

    🧤 알아두어야 할 것

    🖥 서버 캐싱 (서버 단 캐시)

    • 위치: Nginx(리버스 프록시)나 CDN, API Gateway 같은 서버 측
    • 동작:
      1. 첫 요청 → 서버가 백엔드에 요청해 응답 저장
      2. TTL 안의 재요청 → 서버 캐시에서 바로 응답
      3. TTL 지나면 백엔드 재요청
    • 장점:
      • 백엔드 부하 감소 (API·정적 파일 모두 가능)
      • TTL 내에 여러 유저 요청을 합쳐서 처리 가능
      • 브라우저 캐시를 무시하고도 동작 가능 (모든 클라이언트 공통)
    • 단점:
      • TTL 안에서는 변경된 데이터가 바로 반영 안 될 수 있음
      • 서버 디스크/메모리 사용

    예시: proxy_cache (Nginx), CloudFront, Varnish, Redis 기반 캐시

    🌐 브라우저 캐싱 (클라이언트 단 캐시)

    • 위치: 사용자의 웹 브라우저 로컬 저장소
    • 동작:
      1. 첫 요청 시 응답을 브라우저가 저장
      2. TTL 또는 조건부 요청(ETag, Last-Modified) 안에서는 서버에 재요청 없이 바로 로컬에서 로드
      3. TTL 지나면 서버에 새로 요청
    • 장점:
      • 요청 자체를 줄여 네트워크 속도 향상
      • 서버에 트래픽이 아예 가지 않음
    • 단점:
      • 브라우저별·사용자별로 캐시가 따로 있음
      • TTL 안에 새 버전 배포 시 즉시 반영 안 됨
      • 캐시 무효화(무효화 정책, 파일명 변경) 필요

    예시: Cache-Control: max-age=31536000, immutable, ETag + If-None-Match


    🔥 빌드할때 왜 해시 기반 파일명으로 할까?

    📌 해시 기반 파일명의 핵심 목적: 

    캐시 무효화(Cache Busting)

    • 브라우저 캐싱은 빠른 로딩을 위해 오래 저장하지만, 이게 변경 반영에는 치명적일 수 있음.
    • 파일명이 고정이면 (app.js), 브라우저는 TTL 동안 절대 새로 다운로드 안 함.
    • 그래서 파일 내용이 바뀔 때마다 내용 기반 해시(MD5/SHA1 등)를 파일명에 포함시켜 버전처럼 사용.
    빌드 전빌드 후
    /static/app.js/static/app.9fceb3d2.js
    /static/style.css/static/style.ae3d9c9f.css

    🛠 동작 방식

    1. 빌드 시 JS/CSS 내용의 해시를 계산
    2. 해시를 파일명에 삽입
    3. HTML에서 그 새 파일명을 참조
    4. 브라우저는 이름이 다르면 다른 파일로 인식 → 즉시 새로 다운로드

    ✅ 장점

    1. 1년 캐시 가능
      • 파일명이 바뀌면 브라우저는 무조건 새로 받음 → TTL 무시
    2. 불필요한 네트워크 요청 제거
      • 내용이 안 바뀌면 계속 기존 캐시 사용
    3. CDN/프록시 캐시 효율 극대화
      • 전 세계 캐시 서버에 동일한 파일명이 유지

    ⚠️ 단점

    • 빌드 과정에서 HTML/JS 내부의 파일 경로를 전부 갱신해야 함
    • 해시 값이 조금이라도 달라지면 완전히 새 파일로 인식 → 캐시 100% 무효화 (좋기도 하고, 비효율일 수도 있음)

    📍 정리

    • 해시 기반 파일명 덕분에 Cache-Control: max-age=31536000, immutable 같은 1년 브라우저 캐싱 정책을 안전하게 쓸 수 있음.
    • 해시 없이 고정 파일명이라면, 이렇게 길게 캐싱하면 배포 때 문제 생김.

  • 하나의 서버에서 두 도메인 SSL 설정 방법

    하나의 서버에서 두 도메인 SSL 설정 방법

    하나의 서버에서 2개의 웹 프론트 서버가 서로 다른 도메인으로 SSL(443포트) 사용 가능하다. 단, 아래 조건을 만족해야 한다.


    ✅ 전제 조건

    1. 도메인이 서로 다름
      • 예: a.example.com, b.example.com
    2. 각 도메인에 대해 유효한 SSL 인증서
      • Let’s Encrypt 등에서 도메인 별 인증서 발급
    3. 리버스 프록시(Web 서버)가 하나만 443 포트를 바인딩
      • Nginx나 Apache 같은 리버스 프록시를 사용해 도메인에 따라 백엔드 서버로 트래픽 분기

    🧱 구조 예시

    [Client]
       |
    443 포트 요청 (도메인 A 또는 B)
       ↓
    [Nginx Reverse Proxy]  (SSL 인증서 설정, 443 포트 점유)
       ├──> http://localhost:3001 (도메인 A용 웹 앱)
       └──> http://localhost:3002 (도메인 B용 웹 앱)
    # nginx conf 예시
    
    # a.example.com에 대한 설정
    server {
        listen 443 ssl;
        server_name a.example.com;
    
        ssl_certificate     /etc/ssl/certs/a_cert.pem;
        ssl_certificate_key /etc/ssl/private/a_key.pem;
    
        location / {
            proxy_pass http://localhost:3001;
        }
    }
    
    # b.example.com에 대한 설정
    server {
        listen 443 ssl;
        server_name b.example.com;
    
        ssl_certificate     /etc/ssl/certs/b_cert.pem;
        ssl_certificate_key /etc/ssl/private/b_key.pem;
    
        location / {
            proxy_pass http://localhost:3002;
        }
    }

    📝 요약

    항목가능 여부설명
    443 포트 공유 가능Nginx나 Apache 하나만 점유하고 도메인 분기로 분리
    서로 다른 도메인 사용server_name으로 분기 가능
    SSL 인증서 동시 적용도메인별 인증서 각각 설정 필요

    📌 SSL 없이도 가능? (HTTP:80)

    SSL 인증서를 사용하지 않고 하나의 서버에서 두 개의 웹 프론트 서버를 서로 다른 도메인으로 띄우는 것도 가능하다. 이 경우엔 443 포트가 아니라 80포트로 사용하게 된다.

    ✅ 요약: SSL 없이 가능한가?

    조건가능 여부설명
    SSL 없이 HTTP만 사용할 경우80 포트는 여러 도메인에서 공유 가능
    도메인 별로 서비스 가능server_name으로 도메인 분기 가능
    보안 (HTTPS) 없음모든 트래픽이 암호화되지 않음 (보안 취약)

    ⚠️ 주의할 점

    • 중간자 공격(MITM)에 취약 → 로그인, 개인정보 송수신이 있다면 반드시 SSL 사용 권장
    • 일부 브라우저에서는 HTTPS 필수로 요구 → 특히 PWA, 모바일 앱, OAuth, API 연동 등에서 문제 발생 가능

    💬 결론

    도메인이 있다면 포트를 나눌 필요 없음. Nginx 같은 리버스 프록시로 하나의 포트(80/443)에서 라우팅 가능

    도메인이 없으면 포트를 나눠야 함. 각 서비스가 독립된 포트를 차지해야 하므로

  • AWS Certified Solution Architect | 클라우드 컴퓨팅, AWS 개요 — 클라우드 컴퓨팅과 가상화

    AWS Certified Solution Architect | 클라우드 컴퓨팅, AWS 개요 — 클라우드 컴퓨팅과 가상화

    📌 클라우드 컴퓨팅과 가상화

    모든 클라우드 컴퓨팅 서비스의 핵심 기술은 가상화에 기반

    가상화란.

    하나의 물리적 서버 형태로 존재하는 하드웨어 리소스를 여러 개의 작은 유닛으로 나누는 것임.

    가상의 작은 유닛으로 분할된 물리적 서버는 자체 운영체제, 유닛별 메모리, 스토리지 네트워크를 할당 받은 가상 머신이 되어 작동할 수 있게 됨.

    가상화 기술은 사용자가 가상 서버를 불과 수 초만에 배포, 프로젝트 요구 사항에 맞춰 실행한 뒤, 즉시 삭제할 수 있을 정도로 높은 유연성 제공.

    🚧 클라우드 컴퓨팅 아키텍처

    AWS와 같은 주요 클라우드 서비스 제공사는 수십만 대의 서버, 디스크 드라이버를 네트워크 케이블로 연결한 방대한 규모의 서버 팜을 운영.

    🚧 클라우드 컴퓨팅 최적화

    클라우드는 확장성 및 탄력성을 지니고 있으며, 전통적인 시스템에 비해 훨씬 낮은 비용이 소요. 변동성 높은 워크로드 처리를 위한 탁월한 선택이 될 수 있음. 사용자는 효과적인 클라우드 리소스 배포를 위해 이들 세 가지 속성에 대한 나름의 감각 또는 인사이트를 지니고 있어야 함.

    🍃 확장성

    인프라의 확장성이 높다는 의미는 사용자의 애플리케이션에 예측하지 못한 트래픽이 몰렸을 때, 이를 해소하기 위한 리소스를 자동으로 추가할 수 있다는 것.

    AWS는 사전 정의된 요구 수준에 맞춰서 필요한 즉시 자동으로 머신 이미지를 복제해서 론칭할 수 있는 Auto scaling 서비스를 제공.

    🍃 탄력성

    탄력성 원칙 또한 확장성과 같이 요구 수준 변화에 대해 시스템이 어떻게 반응하도록 할 것인가 하는 문제를 다룸. 탄력성이 확장성과 다른 부부은 확장성은 수요 증가에 따라 리소스를 증대시키는 개념이라면, 탄력성은 수요 감소에 따라 리소스를 감소시키는 개념을 포함하고 있다. 사용자는 꼭 필요할 때만 리소스를 실행하면 되므로 클라우드 비용을 효과적으로 통제할 수 있다.

    🍃 비용관리

    여러분이 사용하는 리소스의 양과 관련된 비용을 통제하는 것과 별개로 클라우드 컴퓨팅은 IT 인프라 도입 및 운영을 기존의 자본 비용에서 운영 비용 관점으로 변화시킴.

    클라우드 기반의 총 운영 비용이 전통적인 데이터 센터 구축 및 운영 비용보다 반드시 낮다는 것은 아니지만 사용자가 장기적인 수요의 관점에서 불필요한 자본적 지출의 리스크를 줄일 수 있는 것은 분명함.

    📌 AWS 클라우드

    AWS service 카테고리

    🎾 Compute

    ⛳️ Compute— Elastic Compute Cloud (EC2)

    EC2 서버 인스턴스는 전통적인 데이터 센터에서 실행되던 서버의 가상화 버전. EC2 인스턴스는 CPU, 메모리, 스토리지, 네트워크 인터페이스 프로필 등과 함께 프로비저닝 되며, 간단한 웹 서버부터 통합 멀티 티어 아키텍처 기반의 클러스터용 인스턴스까지 구현할 수 있다. EC2 인스턴스는 가상화된 리소스이므로, 효율성은 높고 배포는 즉각적으로 이뤄질 수 있음.

    ⛳️ Compute— Lambda

    별도의 서버를 운영 및 관리할 필요 없이 1년 내내 다수의 고객의 요구 수준에 대응하는 애플리케이션 서비스를 재공하기 위한 서버리스 아키텍처 요소. 버튼 클릭과 같은 이벤트에 반응해 미리 지정된 코드를 실행하는 서비스. 최장 15분간의 코드 실행 작업이 완료되면, Lambda 이벤트도 종료되고 코드 실행을 위해 할당됐던 모든 리소스는 자동으로 해제됨.

    ⛳️ Compute — Auto Scaling

    조직에서 널리 사용하는 EC2 인스턴스를 이미지 템플릿으로 저장한 뒤 트래픽 또는 워크로드가 증가 또는 감소하면 이에 대응해 자동으로 인스턴스 이미지를 추가 또는 삭제하는 서비스. 즉, 자동화된 컴퓨팅 리소스의 스케일 아웃 및 스케일 인 도구.

    ⛳️Compute — Elastic Load Balancer

    클라우드 인프라 및 리소스로 유입되는 네트워크 트래픽을 병목 현상이 발생하지 않도록 다수의 서버에 분산시키는 역할. 헬스 체크를 통과하지 못한 인스턴스에게는 요청을 전송하지 않음.

    ⛳️ Compute — Elastic Container Service

    Docker 또는 K8s 등과 같은 컨테이너 기술을 이용해 다른 AWS 계정 소유 리소스와 완벽하게 통합할 수 있는 컴퓨트 워크로드를 프로비전, 자동화, 배포, 관리 업무를 수행할 수 있음. K8s의 경우, 전용의 컴퓨트 워크로드인 EKS를 사용.

    ⛳️ Compute — Elastic Beantalk

    Beantalk는 AWS 컴퓨트와 네트워크 인프라의 프로비저닝을 추상화한 관리형 서비스.개발자가 애플리케이션 코드 작성에만 집중 할 수 있도록 해줌. Beantalk는 애플리케이션 서비스 구현에 필요한 제반 요소를 자동으로 시작 및 관리.


    🎾 Networking

    ⛳️ Virtual Private Cloud.(VPC)

    EC2 및 RDS 인스턴스 호스팅을 위해 만들어진, 고도의 환경설정이 가능한 네트워크 환경. 사용자는 VPC 기반 도구를 이용해 인스턴스의 네트워크 보안을 유지하거나, 외부 환경과 격리해서 인바운드 및 아웃바운드 네트워크 트래픽을 긴밀하게 제어할 수 있음.

    ⛳️ Direct Connect

    속도 및 보안 수준이 높은 전용의 네트워크 연결 서비스를 통해 서드파티 공급자와 AWS를 연결해 로컬 데이터 센터 또는 AWS VPC 전용 네트워크를 구현할 수 있음.

    ⛳️ Route 53

    도메인 등록, 레코드 어드민, 라우팅 프로토콜 관리, 헬스 체크 등의 기능을 제공하는 AWS DNS 서비스로서, 다른 AWS 리소스와 완벽한 통합성을 제공.

    ⛳️ CloudFront

    아마존의 글로벌 분산화 CDN(Content Delivery Network) 서비스다.

    이를 통해 사용자는 글로벌 차원의 엣지 로케이션에 사이트 콘텐츠의 캐시 버전을 저장할 수 있으며, 고객의 요청 시 매우 신속하게 효율적으로 콘텐츠 제공.


    🎾 storage

    ⛳️ Simple Storage Service(S3).

    다목적성, 신뢰성을 갖춘 저렴한 객체 저장 서비스로서 데이터 스토리지 및 백업 용도로 널리 활용. S3는 AWS 기반 상용화 서비스 구현 시 보편적으로 사용되며, 상용화 버전과 관련된 스크립트, 템플릿, 로그 파일 스토리지로 활용.

    ⛳️ S3 Glacier.

    장기간, 저렴하게 대량의 데이터 아카이브를 저장할 수 있도록 해주는 서비스. 일정 시간의 인출 지연 시간이 존재. Glacier 생애 주기는 S3와 긴밀하게 통합돼 관리.

    ⛳️ Elastic Block Store(EBS).

    EC2 인스턴스의 운영 체제 및 각종 실행 데이터를 호스팅하기 위한 지속형 가상 스토리지 드라이브. 물리적 서버에 부탁하는 스토리지 드라이브의 기능 및 파티션 속성을 가상환경에서도 사용할 수 있게 해줌.

    ⛳️ Storage Gateway.

    AWS 클라우드 스토리지를 로컬, 온프레미스 환경과 연결해서 사용할 수 있도록 해주는 하이브리드 스토리지 시스템. 데이터 마이그레이션 및 데이터 백업, 재난 복구 작업의 일부로 활용되기도 함.


    🎾 DataBase

    ⛳️ Relational DataBase Service(RDS).

    안정성, 보안성, 신뢰성을 갖춘 관리형 SQL 데이터베이스 서비스. 사용자는 MySQL, Microsoft SQL Server, Oracle, Amazon이 만든 Aurora 등 다양한 SQL 엔진을 사용할 수 있음.

    ⛳️ DynamoDB.

    신속성, 유연성, 고확장성을 지닌 관리형 NoSQL 데이터베이스 서비스.


    🎾 애플리케이션 관리

    ⛳️ CloudWatch

    프로세스 성능 및 리소스 사용량 모니터링 서비스. 사용자가 미리 정한 기준치에 도달하면, 메시지를 전송하거나 자동화된 응답을 실행.

    ⛳️Cloud Formation

    AWS 리소스 배포를 위한 완벽하면서도 복합적인 요구 사항 정의 템플릿을 제공. 사용자는 AWS 인프라에 대한 스크립트를 작성해 자동화된 리소스 관리가 가능, 애플리케이션 론칭 프로세스를 표준화, 간소화할 수 있음.

    ⛳️ CloudTrail

    API 이벤트와 관련된 모든 사용자 계정의 기록을 수집해서 감사 업무 및 시스템 문제 해결에 활용.

    ⛳️ Config

    AWS 계정과 관련된 변경 사항 관리 및 규정 준수 업무를 지원. 사용자가 바람직한 형태의 환경설정 상태를 정의하면, Config는 정의된 내용과 다른 변경 사항을 감지 및 평가하게 됨. 변경 사항과 미리 정의된 내용과의 격차가 일정 수준 이상인 경우, 알림 메시지를 발송.


    🎾 보안 및 권한 관리

    ⛳️ Identity and Access Management(IAM)

    AWS 계정에 대한 특정 사용자 또는 프로그래밍 차원의 접근을 관리 하기 위한 서비스. 유저, 그룹, 역할, 정책 등 개념을 통해 AWS 리소스에 누가, 어떤 작업을 위해 접근하게 할지 매우 상세하게 지정할 수 있음.

    ⛳ Key Managerment Service(KMS)

    AWS 리소스와 관련된 보안 데이터의 암호화 키 생성 및 관리를 위한 어드민 서비스.

    ⛳️ Directory Service

    AWS 리소스의 활용을 위해, Amazon Cognito 및 Microsoft AD 도메인 등 내외부의 신원 인증 제공 서비스와 통합 관리할 수 있도록 함.


    🎾 애플리케이션 통합

    ⛳️ Simple Notification Service(SNS)

    SQS, Lambda 등 다른 서비스나 모바일 기기에게 자동으로 알림 또는 경고 메시지를 보내거나 다른 수신자에게 이메일 또는 SMS를 전송하는 서비스.

    ⛳️ Simple Workflow(SWF)

    일련의 AWS 서비스 또는 디지털화할 수 없는 (사람의 특정 동작이 관련된) 이벤트를 포함하는 연속적인 작업 관리 서비스.

    ⛳️ Simple Queue Service(SQS)

    분산 시스템 등 대규모 프로세스에 포함된 다수의 업무 단계를 느슨하게 연결해 유연한 처리를 돕는, 이벤트 기반 메시징 서비스. SQS 메시지에 담긴 데이터는 신뢰할 수 있는 방식으로 전달돼, 애플리케이션의 내오류성을 높일 수 있음.

    ⛳️ API Gateway

    AWS 기반 애플리케이션을 위한 안전하며, 신뢰할 수 있는 API를 생성하고 관리하기 위한 서비스.

  • Apache와 Nginx에서 SSL 파일 형식 통합하기

    Apache와 Nginx에서 SSL 파일 형식 통합하기

    apache와 nginx에서 쓰는 SSL 파일형식이 다름. 각각 만들어줘야 하지만, 통합해서 쓸 수 있는 방법이 있다.

    인증서와 체인 파일을 하나로 합친 파일을 생성하고, 이를 웹 서버에서 공통적으로 사용하도록 설정하면 된다.

    cat star_crt.pem ChainCA.crt RootCA.crt > fullchain.pem

    fullchain.pem 파일과 Private.key 파일을 웹 서버 설정

    apache 설정

    <VirtualHost *:443>
        ServerName example.com
    
        SSLEngine on
        SSLCertificateFile /path/to/fullchain.pem
        SSLCertificateKeyFile /path/to/Private.key
    </VirtualHost>

    nginx 설정

    server {
        listen 443 ssl;
        server_name example.com;
    
        ssl_certificate /path/to/fullchain.pem;
        ssl_certificate_key /path/to/Private.key;
    }

    ✅ AWS SSL 인증서 등록하기

    1. SSL 인증서(AWS 콘솔에서 “Certificate body”):

    star_newssalad_com_crt.pem 파일의 내용을 사용합니다. 이 파일은 기본 인증서 파일입니다.

    2. 중간 인증서 (AWS 콘솔에서 “Certificate chain”):

    ChainCA.crt와 RootCA.crt 파일을 결합한 내용을 사용해야 합니다. 이 두 파일을 합쳐서 중간 인증서로 등록하면 됩니다.

    cat ChainCA.crt RootCA.crt > certificate_chain.pem

    3. 개인 키 (AWS 콘솔에서 “Certificate private key”):

    Private.key 파일의 내용을 사용합니다.


    • Certificate body: star_newssalad_com_crt.pem의 내용
    • Certificate chain: certificate_chain.pem의 내용 (위에서 생성한 파일)
    • Certificate private key: Private.key의 내용

    암호화된 개인 키 복호화

    만약 .key 파일이 암호화되어 있다면, AWS에서는 복호화된 개인 키가 필요합니다. 개인 키가 암호화된 경우 openssl 명령을 사용해 암호를 제거할 수 있습니다.

    openssl rsa -in Private.key -out Private_unencrypted.key
  • NHN Cloud에서 인증서 설정하기

    NHN Cloud에서 인증서 설정하기

    📄 인증서 파일 결합 및 적용 방법

    지금 보유한 파일을 활용해 단일 .pem 파일을 생성하고 Certificate Manager에 적용하는 방법을 설명합니다.


    📂 파일 확인 및 준비

    | 파일명                         | 설명                               |
    |--------------------------------|----------------------------------|
    | star_example_com_crt.pem     | 메인 인증서 파일                  |
    | certificate_chain.pem          | 체인 인증서 파일 (Intermediate CA) |
    | ChainCA.crt                    | 대체 체인 인증서 파일             |
    | Private.key                    | 개인 키 파일                      |
    | Private_unencrypted.key        | 암호화되지 않은 개인 키 파일       |
    | RootCA.crt                     | 루트 인증서 파일 (선택 사항)       |

    📌 개인키 암호화 변경

    후이즈(whois) 에서 제공하는 개인키는 PKCS8 암호화로 되어 있어, 아래와 같이 RSA 암호화로 변경해야 한다.

    openssl rsa -des3 -in *.key -out *_pass.key

    생성한 RSA 암호화 개인키를 아래 명령어로 RSA 비암호화 개인키로 변환.

    openssl rsa -in *_pass.key -out *_nopass.key

    📌 NHN Cloud에 맞게 .pem 파일 제작

    • NHN에 외부인증서 등록시 들어가야하는 파일순서

    보안서버인증서 — 루트인증서 — 체인인증서 — 개인키

    (도메인명_crt.pem - RootCA.crt - ChainCA.crt - *.key)

    🚀 Certificate Manager에 적용

    1. 위에서 만든 bundle.pem파일을 Certificate Manager에 업로드합니다
    2. 업로드 후 정상적으로 적용되었는지 테스트
  • 최적화된 AWS MariaDB 성능 튜닝 전략

    최적화된 AWS MariaDB 성능 튜닝 전략

    AWS | mariaDB RDS 튜닝

    튜닝을 해야 하는 것만 기록했다.

    마리아 디비 [10.3.30 버전]

    파라미터현재 설정값개념
    character_set_clientutf8mb4클라이언트가 서버로 데이터를 보낼 때 사용하는 문자 인코딩 설정입니다.
    character_set_connectionutf8mb4클라이언트가 서버에 보낸 쿼리의 문자셋을 서버 내부에서 변환할 때 사용됩니다.
    character_set_databaseutf8mb4데이터베이스가 생성될 때 적용되는 기본 문자셋입니다.
    character_set_filesystemutf8mb4파일 시스템에서 사용하는 문자셋입니다.
    character_set_resultsutf8mb4서버가 클라이언트에 결과 데이터를 보낼 때 사용하는 문자셋입니다.
    character_set_serverutf8mb4서버의 기본 문자셋으로 새 데이터베이스나 테이블에 적용됩니다.
    collation_connectionutf8mb4_unicode_ci클라이언트와 서버 간 문자셋 비교 및 정렬 방법 설정입니다.
    collation_serverutf8mb4_unicode_ci서버의 기본 문자 비교 및 정렬 방법 설정입니다.
    event_schedulerONMySQL 이벤트 스케줄러를 활성화/비활성화하는 설정입니다.
    general_log0모든 쿼리를 기록하는 일반 로그 설정입니다.
    log_queries_not_using_indexes0인덱스를 사용하지 않는 쿼리를 기록하는 설정입니다.
    long_query_time2느린 쿼리 로그에 기록될 기준 시간을 초 단위로 설정합니다.
    slow_query_log0느린 쿼리를 기록하는 설정입니다.
    time_zoneAsia/Seoul데이터베이스 서버의 시간대(Time Zone)를 설정합니다.
    tx_isolationREAD-COMMITTED트랜잭션의 격리 수준 설정으로 일관성 있는 커밋된 데이터만 읽게 됩니다.
    lock_wait_timeout86400

    마리아 디비 [10.6.30 버전]

    파라미터현재 설정값설명
    character_set_clientutf8mb4클라이언트에서 사용하는 문자셋
    character_set_connectionutf8mb4연결 시 문자셋 변환에 사용되는 설정
    character_set_databaseutf8mb4데이터베이스의 기본 문자셋
    character_set_filesystemutf8mb4파일 시스템에서 사용하는 문자셋
    character_set_resultsutf8mb4서버가 결과를 반환할 때의 문자셋
    character_set_serverutf8mb4서버의 기본 문자셋
    collation_connectionutf8mb4_unicode_ci문자 정렬 및 비교 방법 설정
    collation_serverutf8mb4_unicode_ci서버의 기본 문자 정렬 및 비교 규칙
    log_bin_trust_function_creators1저장 함수 생성 시 권한 설정
    time_zoneAsia/Seoul서버의 시간대 설정
    tx_isolationREAD-COMMITTED트랜잭션의 격리 수준 설정으로 일관성 있는 커밋된 데이터만 읽게 됩니다
    lock_wait_timeout86400

    ✅ 공통사항 (확인해봐야 할 사항)

    SQL_BIG_SELECTS 튜닝

    SQL_BIG_SELECTS=1
    ---
    # NHN에서는
    max_join_size 값을 최대값으로 변경하면 SQL_BIG_SELECTS=1로 변경됨.

    📌 binlog 관련 튜닝(데이터베이스 이관 시, 지속적 복제 사용할 시)

    파라미터설명옵션*RDS 기본값
    binlog_format바이너리 로그의 형식`ROW`, `STATEMENT`, `MIXED`ROW
    log_bin바이너리 로그 활성화 여부`ON`, `OFF``ON` (고정)
    `log_bin_trust_function_creators`저장 함수 생성 시 권한 설정`0` (OFF), `1` (ON)`0`
    sync_binlog로그 동기화 빈도`0`, `1`, `1`1
    binlog_row_imageROW 포맷 이미지 범위`FULL`, `MINIMAL`, `NOBLOB`FULL
    max_binlog_size하나의 로그 파일 최대 크기숫자 (Bytes)1GB
    expire_logs_days바이너리 로그 보관 기간숫자(일), `0`7
    binlog_cache_size바이너리 로그 캐시 크기숫자 (Bytes)32KB
    binlog_checksum로그 무결성 체크섬 설정`NONE`, `CRC32`CRC32

    innoDB 메모리 관련 튜닝

    innodb_buffer_pool_size: {DBInstanceClassMemory*3/4}

    🛠️ mariaDB 메모리 관련 튜닝

    AWS 파라미터 기준.
    ----
    
    thread_stack: 262144
    net_buffer_length: 16384
    read_buffer_size: 262144
    sort_buffer_size: 2097152 -> 1048576
    join_buffer_size: 262144
    max_heap_table_size: 16777216
    tmp_table_size: 16777216
    binlog_cache_size: 32768
    read_rnd_buffer_size: 16777216(16MB)[변경 전] -> 524288(512KB)[변경 후]

    🛠️ max_connection 튜닝

    AWS 파라미터 기준.
    ----
    {DBInstanceClassMemory/12582880}
    
    nhn.
    ----
    ramSizeByte / 12582880

    🛠️ connection 튜닝

    바꾸려는 이유

    특정시간 DB가 클라이언트의 연결을 끊어버리는 현상이 일어남

    1. 파라미터 값 확인
    
    - net_read_timeout  : 서버가 클라이언트로부터 데이터를 읽어들이는 것을 중단하기까지 대기하는 시간
    - connect_timeout : 서버 접속시에 접속실패 메세지를 보내기까지 대기하는 시간
    - max_allowed_packet : 서버로 질의하거나 받게되는 패킷의 최대 길이
    
    ---
    net_read_timeout: 30 -> 60
    connect_timeout: 10 -> 30
    max_allowed_packet: 이미 최댓값. -> X
    
    으로 바꿔 봄.
    
    ---
    
    interactive_timeout 28800 => 7200 -> 3600
    wait_timeout 28800 => 7200 -> 3600

    🔖 MySQL 8.0.40 Version 추가 파라미터 튜닝

    sql_mode: 
    STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION

  • EC2 인스턴스 스토리지 확장 가이드

    EC2 인스턴스 스토리지 확장 가이드

    aws instance EC2의 스토리지를 확장하기 위해서는 따로 instance를 다운시키거나 할 필요가 없다.

    먼저 AWS 콘솔에서 내가 늘리고 싶은 스토리지를 볼륨 수정을 해준다.

    볼륨 수정이 되었다면, 서버에 접속해서 몇가지 작업을 해줘야 한다.

    lsblk
    
    ---
    NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    xvda    202:0    0  20G  0 disk
    └─xvda1 202:1    0  10G  0 part /

    확장된 스토리지를 확인 한 후,

    • growpart로 파티션 크기 확장
    sudo growpart /dev/vda 1
    • 파일 시스템 크기 확장
    • ext4 파일 시스템:
    sudo resize2fs /dev/xvdf1
    • xfs 파일 시스템:
    sudo xfs_growfs /dev/xvdf1
    • 확장 확인
    df -h

    ✅ 파일 시스템 종류를 알아보려면..

    lsblk -f

    이렇게 치면 파일 시스템 종류가 나온다.

    📌 NHN Cloud 스토리지 확장하는 법

    growpart 명령어로 파티션 확장

    # Example.
    
    growpart 디바이스 이름 example -> /dev/vda 5

    참고 : growpart는 cloud-utils-growpart 패키지에 포함. 설치 필요할 수도 있음.

    yum install cloud-utils-growpart -y

    파일 시스템 확장

    # file system check
    lsblk -f
    
    # ext4 파일 시스템.
    
    resize2fs 디바이스 이름 example -> /dev/vda5
    
    # xfs 파일 시스템.
    
    xfs_growfs /

    변경 확인

    lsblk
    df -h
  • Load balancer Timeout 오류

    Load balancer Timeout 오류

    AWS Load balancer로 구축된 웹 서버와 API 서버가 있다.

    • A load balancer — Nginx 웹 서버 (instance 3대)
    • B load balancer — API 서버 (instance 3대)

    이렇게 각각 2개의 로드밸런서를 구축하고 아무런 문제 없이 운영하고 있는데 오류가 발생했다.

    오류의 내용은, timeout error 였다.

    2024/11/05 14:40:24 [error] 905#0: *974 upstream timed out (110: Connection timed out) while reading response header from upstream

    이런 내용의 에러 였다.

    구글링을 해보니, 프록시 서버에서의 읽는 시간과 연결 시간이 너무 짧게 설정되어 있어서 해당 오류가 뜬다고 나와있다.

    nginx.conf 파일을 살펴보니 따로 timeout에 대해 설정이 되어 있진 않았다. 설정이 되어있지 않다면 디폴트값은 다음과 같다.

    proxy_connect_timeout: 60초
    proxy_read_timeout: 60초
    proxy_send_timeout: 60초

    일단 로드밸런서의 서버 리소스는 충분했고, DB 지연시간이나 DB CPU가 많이 먹는 상태는 아니었기 때문에 1순위로 timeout 설정이 잘못되어 졌다고 생각했다.

    오류가 난 서버에 위 설정을 두배정도인 120s 로 설정 했다.

    proxy_connect_timeout 120s;
    proxy_read_timeout 120s;
    proxy_send_timeout 120s;

    그리고, 한가지 더 의심이 갔던 부분은 로드밸런서를 구성할 때 대상그룹의 상태검사 부분에서 health check 하는 부분이 있다.

    여기서도 timeout — 제한시간이라는 이름으로 응답에 관련한 항목이 있다.

    이 부분도 web 서버의 로드밸런서와 api 서버의 로드밸런서가 서로 시간이 상이했기 때문에 upstream timeout 에러가 났다고 추측했다.

    제한시간 타임을 조금 늘리고, 각각의 로드밸런서의 시간을 동일하게 맞췄다.

    그리고 나서는 따로 오류가 나지 않는 상태.

  • Locky Linux 8 (CentOS7) | WEB 서버 Setting

    Locky Linux 8 (CentOS7) | WEB 서버 Setting

    관련 패키지 및 버전

    nginx — 1.26.2, node.js — 16.20.2, npm — 8.19.4, pm2–5.4.2

    selinux 설정 끄기

    sudo getenforce # enforce 상태 확인.
    sudo setenforce 0 # enforce 상태 변경. (끄기)

    📌 selinux 영구적으로 끄는 법

    # 파일 수정.
    sudo vi /etc/selinux/config
    # 이 항목을 찾는다.
    SELINUX=enforcing
    # 다음과 같이 변경.
    SELINUX=disabled
    # 시스템 재부팅.
    sudo reboot
    # 적용되었는지 확인.
    sestatus

    커널 sysctl 수정 (소켓 maxconn 셋팅값 수정.) -> maxconn 값은 상황에 따라 수정 가능

    # maxconn 상태 조회.
    sudo sysctl -a | grep net.core.somaxconn
    # maxconn 상태 수정.
    sudo /sbin/sysctl -w net.core.somaxconn=4096
    
    ---
    net.core.somaxconn = 65535

    port 체크

    sudo netstat -nltup

    시스템 업데이트 및 필수 패키지 설치

    sudo dnf update -y
    sudo dnf install -y curl wget tar gcc-c++ make

    Nginx 셋팅 (version : 1.26.2)

    # 필요한 패키지 설치
    sudo dnf install -y gcc pcre-devel zlib-devel make openssl-devel
    # Nginx 소스 다운로드
    wget https://nginx.org/download/nginx-1.26.2.tar.gz
    # 압축 해제 및 설치
    tar -zxvf nginx-1.26.2.tar.gz
    cd nginx-1.26.2
    # Nginx 컴파일 및 설치
    ./configure
    make
    sudo make install
    # Nginx 실행 확인
    /usr/local/nginx/sbin/nginx -v

    Nginx 환경변수 설정

    vi ~/.bashrc # 해당 파일에 아래와 같은 내용 추가.
    export PATH=$PATH:/usr/local/nginx/sbin
    source ~/.bashrc # 적용.
    nginx -v # 확인.

    Nginx 서비스 설정

    root ~ # vi /etc/systemd/system/nginx.service
    
    [Unit]
    Description=The NGINX HTTP and reverse proxy server
    After=network.target
    
    [Service]
    Type=forking
    PIDFile=/usr/local/nginx/logs/nginx.pid
    ExecStartPre=/usr/local/nginx/sbin/nginx -t
    ExecStart=/usr/local/nginx/sbin/nginx
    ExecReload=/usr/local/nginx/sbin/nginx -s reload
    ExecStop=/usr/local/nginx/sbin/nginx -s stop
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    
    ---
    
    systemctl daemon-reload
    systemctl status nginx
    systemctl start nginx
    systemctl enable nginx

    Node.js 16.20.2 설치

    # nvm 설치
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
    source ~/.bashrc
    # nvm으로 Node.js 16.20.2 설치
    nvm install 16.20.2
    nvm use 16.20.2
    # 설치된 Node.js 버전 확인
    node -v
    npm -v

    NPM 8.19.4 설치

    #### 위에서 버전이 나오면 따로 설치 안해도 됨.
    npm install -g npm@8.19.4
    # 설치된 NPM 버전 확인
    npm -v

    PM2 5.4.2 설치

    npm install -g pm2@5.4.2
    # PM2 버전 확인
    pm2 -v

    PM2 사용법

    # 애플리케이션 시작
    pm2 start app.js
    # 모든 애플리케이션 목록 확인
    pm2 list
    # 애플리케이션 로그 확인
    pm2 logs
    # 애플리케이션 재시작
    pm2 restart app
    # PM2 상태 저장 (서버 재부팅 시 자동 시작)
    pm2 save
    pm2 startup

  • Ollama 외부 접속

    Ollama 외부 접속

    ollama를 외부접속하게 만들려고 한다. 그래서 ollama 설치 후, systemd 등록 파일로 프로세스를 띄웠다.

    [Unit]
    Description=Ollama Service
    After=network.target
    
    [Service]
    ExecStart=/usr/local/bin/ollama serve
    User=root
    Restart=always
    RestartSec=3
    
    Environment="OLLAMA_HOST=0.0.0.0"
    
    [Install]
    WantedBy=multi-user.target

    default 가 127.0.0.1:11434로 프로세스가 띄워지기 때문에 외부에서 접속할 수 있게 0.0.0.0:11434으로 띄워야 한다. Environment="OLLAMA_HOST=0.0.0.0" 으로 등록하여 anywhere로 접근하게 만들었다.

    하지만, TCP6로만 열리고, TCP4로는 열리지 않았다.

    이런 문제를 해결하기 위해 nginx로 로드밸런서 처리를 하여 외부에서 ollama를 접속할 수 있게 만들었다.

    # /etc/nginx/site-availables/
    
    server {
        listen 11433; # ollama port
    
        location / {
            proxy_pass http://[::1]:11434;  # Ollama 서버의 IPv6 주소와 포트
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

    nginx에서 이렇게 설정하여, nginx에 들어오는 트래픽을 ollama로 들어가게 설정하였다.

    새로운 설정 파일 활성화

    sites-enabled 디렉터리에 올바른 파일이 없기 때문에, 이전에 생성한 ollama 설정 파일을 활성화.

    sudo ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/default

    Nginx 설정 다시 확인

    올바른 파일이 활성화되었는지 확인.

    sudo nginx -t