Nginx 설정 가이드 — 리버스 프록시, SSL, 캐싱

Nginx 개요

Nginx(엔진엑스)는 높은 동시 접속 처리 성능으로 알려진 웹서버이자 리버스 프록시 서버입니다. Apache가 요청마다 프로세스/스레드를 생성하는 방식인 반면, Nginx는 이벤트 기반 비동기 아키텍처로 적은 메모리로 수만 개의 동시 연결을 처리합니다.

주요 용도는 다음과 같습니다.

용도설명
정적 파일 서빙HTML, CSS, JS, 이미지 등을 직접 제공
리버스 프록시백엔드 서버(Node.js, Django 등) 앞단에서 요청 중계
로드 밸런서여러 백엔드 서버에 트래픽 분산
SSL 종료HTTPS 암호화/복호화를 Nginx에서 처리
캐싱정적 자원과 프록시 응답을 캐싱하여 성능 향상

설치와 기본 설정

Ubuntu/Debian 기준으로 설치합니다.

# Nginx 설치
sudo apt update && sudo apt install -y nginx

# 서비스 시작 및 부팅 시 자동 시작
sudo systemctl enable --now nginx

# 설치 확인
nginx -v
# nginx version: nginx/1.24.0

# 설정 파일 문법 검사
sudo nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 설정 적용 (무중단 리로드)
sudo nginx -s reload

Nginx의 설정 파일 구조입니다.

경로역할
/etc/nginx/nginx.conf전역 설정 (워커 프로세스, 이벤트 등)
/etc/nginx/sites-available/사이트별 설정 파일 (비활성)
/etc/nginx/sites-enabled/활성화된 사이트 (심볼릭 링크)
/etc/nginx/conf.d/추가 설정 파일 (*.conf 자동 로드)

리버스 프록시 설정

Node.js(포트 3000)나 Django(포트 8000) 같은 백엔드 서버를 Nginx 뒤에 배치하는 설정입니다.

# /etc/nginx/sites-available/my-app.conf
# Node.js 앱을 위한 리버스 프록시 설정

# 업스트림 서버 정의 (로드 밸런싱 가능)
upstream backend {
    # 라운드 로빈 방식으로 분산 (기본값)
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    # 접속 유지 (Keep-Alive) 커넥션 수
    keepalive 32;
}

server {
    listen 80;
    server_name example.com www.example.com;

    # 접근 로그와 에러 로그 경로
    access_log /var/log/nginx/my-app-access.log;
    error_log  /var/log/nginx/my-app-error.log;

    # 클라이언트 최대 요청 크기 (파일 업로드 등)
    client_max_body_size 50M;

    # 정적 파일은 Nginx가 직접 서빙
    location /static/ {
        alias /opt/my-app/public/;
        # 30일 캐싱
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # API 및 동적 요청은 백엔드로 프록시
    location / {
        proxy_pass http://backend;
        # 원본 클라이언트 정보 전달
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # 프록시 타임아웃 설정
        proxy_connect_timeout 60s;
        proxy_read_timeout 120s;
        proxy_send_timeout 60s;
        # WebSocket 지원
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

사이트를 활성화하고 적용합니다.

# 사이트 활성화 (심볼릭 링크 생성)
sudo ln -s /etc/nginx/sites-available/my-app.conf /etc/nginx/sites-enabled/

# 기본 사이트 비활성화 (필요 시)
sudo rm /etc/nginx/sites-enabled/default

# 설정 검사 후 적용
sudo nginx -t && sudo nginx -s reload

proxy_set_header X-Real-IP는 백엔드에서 실제 클라이언트 IP를 확인하는 데 필수입니다. 이 헤더가 없으면 모든 요청의 IP가 127.0.0.1로 표시됩니다.

Let’s Encrypt SSL 설정

무료 SSL 인증서를 Certbot으로 발급받고 Nginx에 적용합니다.

# Certbot 설치
sudo apt install -y certbot python3-certbot-nginx

# SSL 인증서 발급 + Nginx 자동 설정
sudo certbot --nginx -d example.com -d www.example.com
# 이메일 입력 → 이용약관 동의 → HTTP→HTTPS 리다이렉트 선택

# 인증서 자동 갱신 테스트
sudo certbot renew --dry-run

# 인증서 만료일 확인
sudo certbot certificates
# Certificate Name: example.com
# Expiry Date: 2026-05-19 (VALID: 89 days)

Certbot이 Nginx 설정을 자동으로 수정하지만, 수동 설정이 필요한 경우 아래 형태입니다.

# /etc/nginx/sites-available/my-app.conf
# SSL 적용 설정

# HTTP → HTTPS 리다이렉트
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # SSL 인증서 경로
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # SSL 보안 설정 (Mozilla Modern 권장)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS (6개월)
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

    # OCSP Stapling (인증서 유효성 검증 속도 향상)
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

정적 파일 캐싱과 gzip

정적 자원의 캐싱과 gzip 압축으로 응답 속도를 개선합니다.

# /etc/nginx/conf.d/optimization.conf
# 성능 최적화 설정

# gzip 압축 설정
gzip on;
gzip_vary on;
gzip_proxied any;
# 압축 레벨 (1~9, 높을수록 CPU 사용 증가)
gzip_comp_level 6;
# 1KB 미만은 압축하지 않음
gzip_min_length 1024;
# 압축 대상 MIME 타입
gzip_types
    text/plain
    text/css
    text/javascript
    application/javascript
    application/json
    application/xml
    image/svg+xml;

# 파일 캐싱 (확장자별)
server {
    # ... 기존 설정 ...

    # 이미지, 폰트 — 1년 캐싱
    location ~* \.(jpg|jpeg|png|gif|ico|svg|woff2|woff|ttf)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        # 접근 로그 비활성화 (정적 파일 로그가 불필요한 경우)
        access_log off;
    }

    # CSS, JS — 30일 캐싱
    location ~* \.(css|js)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

    # HTML — 캐싱하지 않음 (항상 최신 버전 제공)
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}

유용한 설정 패턴

Rate Limiting (요청 제한)

# 전역 설정 (/etc/nginx/nginx.conf의 http 블록)
# IP당 초당 10개 요청으로 제한 (zone 메모리 10MB)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    location /api/ {
        # burst=20: 순간적으로 20개까지 허용 (큐에 대기)
        # nodelay: 큐에 넣지 않고 즉시 처리
        limit_req zone=api_limit burst=20 nodelay;
        # 제한 초과 시 429 반환
        limit_req_status 429;
        proxy_pass http://backend;
    }
}

보안 헤더

# 보안 관련 응답 헤더
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

실전 팁

  • 설정 변경 전 반드시 nginx -t로 문법을 검사하세요. 문법 오류가 있으면 reload 시 Nginx가 기존 설정으로 계속 동작하지만, restart는 서비스가 중단될 수 있습니다.
  • 무중단 적용: nginx -s reload는 기존 커넥션을 유지하면서 새 설정을 적용합니다. restart와 달리 다운타임이 없습니다.
  • 로그 로테이션: /etc/logrotate.d/nginx 파일로 로그 로테이션이 자동 설정됩니다. 대용량 트래픽 서비스에서는 주기를 조정하세요.
  • 업스트림 헬스체크: 오픈소스 Nginx에서는 max_fails=3 fail_timeout=30s 옵션으로 간단한 헬스체크를 구현할 수 있습니다. Nginx Plus에서는 능동적 헬스체크를 지원합니다.
  • 디버깅: error_log /var/log/nginx/debug.log debug;로 디버그 레벨 로그를 활성화하면 리버스 프록시 문제를 진단할 때 유용합니다. 운영 환경에서는 반드시 비활성화하세요.

이 글이 도움이 되었나요?