Nginx 캐시·성능 최적화

Nginx 성능 최적화가 중요한 이유

Nginx는 리버스 프록시, 정적 파일 서빙, 로드밸런싱을 동시에 담당하는 웹 인프라의 핵심입니다. 기본 설정만으로도 동작하지만, 프록시 캐시, Gzip 압축, Upstream 튜닝을 적용하면 응답 속도와 서버 부하를 획기적으로 개선할 수 있습니다.

Proxy Cache 설정

Nginx의 proxy_cache는 백엔드 응답을 디스크/메모리에 캐싱하여 동일 요청 시 백엔드를 호출하지 않습니다.

# /etc/nginx/nginx.conf (http 블록)
http {
    # 캐시 존 정의: 10MB 메모리 키 영역, 최대 1GB 디스크
    proxy_cache_path /var/cache/nginx/api
        levels=1:2
        keys_zone=api_cache:10m
        max_size=1g
        inactive=60m
        use_temp_path=off;

    proxy_cache_path /var/cache/nginx/static
        levels=1:2
        keys_zone=static_cache:5m
        max_size=2g
        inactive=7d;
}
# server 블록에서 캐시 적용
server {
    listen 443 ssl http2;
    server_name api.example.com;

    # API 응답 캐시
    location /api/products {
        proxy_pass http://backend;
        proxy_cache api_cache;
        proxy_cache_valid 200 10m;      # 200 응답: 10분
        proxy_cache_valid 404 1m;       # 404 응답: 1분
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_use_stale error timeout updating
                              http_500 http_502 http_503;

        # 캐시 상태 헤더 (디버깅용)
        add_header X-Cache-Status $upstream_cache_status;
    }

    # 정적 파일 캐시 (장기)
    location /static/ {
        proxy_pass http://cdn_backend;
        proxy_cache static_cache;
        proxy_cache_valid 200 7d;
        proxy_ignore_headers Cache-Control Expires;
    }
}
X-Cache-Status 의미
HIT 캐시에서 응답
MISS 캐시 없음, 백엔드 호출
STALE 만료된 캐시 사용 (백엔드 장애 시)
UPDATING 갱신 중, 이전 캐시 제공
BYPASS 캐시 우회 (proxy_cache_bypass)

캐시 우회와 퍼지

# 로그인 사용자는 캐시 우회
proxy_cache_bypass $http_authorization;
proxy_no_cache $http_authorization;

# 특정 쿠키가 있으면 캐시 안 함
map $http_cookie $no_cache {
    default         0;
    "~*session_id"  1;
}
proxy_no_cache $no_cache;

# 캐시 퍼지 (nginx-cache-purge 모듈)
location ~ /purge(/.*) {
    allow 10.0.0.0/8;
    deny all;
    proxy_cache_purge api_cache "$scheme$request_method$host$1";
}

Gzip·Brotli 압축

응답 본문을 압축하면 전송 크기를 60~80% 줄일 수 있습니다.

http {
    # Gzip 압축
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;          # 1~9, 5가 성능/압축률 균형점
    gzip_min_length 256;        # 256B 이하는 압축 안 함
    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/json
        application/xml
        image/svg+xml
        font/woff2;

    # Brotli 압축 (ngx_brotli 모듈 필요, Gzip보다 15~20% 더 작음)
    brotli on;
    brotli_comp_level 4;
    brotli_types
        text/plain
        text/css
        application/javascript
        application/json
        image/svg+xml;
}
설정 권장값 이유
gzip_comp_level 4~6 7 이상은 CPU 대비 압축률 향상 미미
gzip_min_length 256 작은 응답은 압축 오버헤드가 더 큼
gzip_proxied any 프록시된 요청도 압축

Upstream 로드밸런싱 튜닝

Nginx 리버스 프록시 실전 가이드에서 기본 설정을 다뤘다면, 여기서는 성능 최적화에 집중합니다.

upstream backend {
    # 최소 연결 수 기반 라우팅
    least_conn;

    # keepalive 커넥션 풀
    keepalive 32;
    keepalive_timeout 60s;
    keepalive_requests 1000;

    server 10.0.1.10:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.1.12:8080 weight=1 backup;  # 백업 서버
}

server {
    location /api/ {
        proxy_pass http://backend;

        # Upstream keepalive 필수 설정
        proxy_http_version 1.1;
        proxy_set_header Connection "";

        # 타임아웃 설정
        proxy_connect_timeout 5s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;

        # 버퍼링 최적화
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 8 8k;
        proxy_busy_buffers_size 16k;

        # 실패 시 다음 서버로 재시도
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
        proxy_next_upstream_timeout 10s;
    }
}

로드밸런싱 알고리즘

알고리즘 설정 적합한 상황
Round Robin 기본값 서버 스펙 동일, 균등 분배
Least Connections least_conn 요청 처리 시간이 불균일
IP Hash ip_hash 세션 어피니티 필요
Random Two random two least_conn 대규모 클러스터, 부하 분산 최적

Worker·Connection 튜닝

# /etc/nginx/nginx.conf
worker_processes auto;          # CPU 코어 수만큼 자동 설정
worker_rlimit_nofile 65535;     # 파일 디스크립터 한도

events {
    worker_connections 4096;    # 워커당 동시 연결 수
    multi_accept on;            # 한 번에 여러 연결 수락
    use epoll;                  # Linux epoll 사용
}

http {
    sendfile on;
    tcp_nopush on;              # sendfile과 함께 사용, 패킷 최적화
    tcp_nodelay on;             # 작은 패킷 즉시 전송
    
    # 클라이언트 타임아웃
    client_body_timeout 12s;
    client_header_timeout 12s;
    send_timeout 10s;
    
    # 연결 재사용
    keepalive_timeout 65s;
    keepalive_requests 100;
    
    # 요청 크기 제한
    client_max_body_size 10m;
    client_body_buffer_size 128k;
}

최대 동시 연결 수 = worker_processes × worker_connections. 4코어에 4096이면 최대 16,384 동시 연결을 처리합니다.

보안 헤더와 SSL 최적화

Nginx Rate Limiting 심화와 함께 적용하면 완성도 높은 보안 설정이 됩니다.

server {
    # SSL 최적화
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_prefer_server_ciphers off;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 1.1.1.1 valid=300s;

    # 보안 헤더
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security
        "max-age=63072000; includeSubDomains; preload" always;
    add_header Referrer-Policy strict-origin-when-cross-origin always;
}

정리

Nginx 성능 최적화는 Proxy Cache로 백엔드 부하를 줄이고, Gzip/Brotli로 전송량을 최소화하며, Upstream keepalive로 연결 오버헤드를 제거하는 세 축으로 구성됩니다. Worker 수와 연결 한도를 서버 스펙에 맞게 튜닝하고, SSL Session Cache와 OCSP Stapling으로 TLS 핸드셰이크 비용을 줄이면 체감 성능이 크게 향상됩니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux