Skip to content

필사 모드: Nginx 완전 가이드 2025: 리버스 프록시, 로드 밸런싱, SSL, 캐싱부터 보안까지

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

TOC

1. Nginx란 무엇인가

Nginx(엔진엑스)는 2004년 Igor Sysoev가 C10K 문제를 해결하기 위해 개발한 고성능 웹 서버입니다. 현재 전 세계 웹 서버 시장 점유율 1위를 차지하며, 단순 웹 서버를 넘어 리버스 프록시, 로드 밸런서, HTTP 캐시, API 게이트웨이 등 다양한 역할을 수행합니다.

1.1 Nginx vs Apache

| 항목 | Nginx | Apache |

|------|-------|--------|

| 아키텍처 | 이벤트 드리븐 (비동기) | 프로세스/스레드 기반 |

| 동시 연결 | 수만 ~ 수십만 | 수천 (MPM 설정에 따라) |

| 메모리 사용 | 연결당 수 KB | 연결당 수 MB |

| 정적 파일 | 매우 빠름 | 빠름 |

| 동적 컨텐츠 | 프록시 (FastCGI/uWSGI) | 모듈 내장 (mod_php) |

| 설정 방식 | 중앙 집중형 | .htaccess 분산 가능 |

| URL 재작성 | location 블록 | mod_rewrite |

| 로드 밸런싱 | 내장 | 별도 모듈 필요 |

| 시장 점유율 | 약 34% (1위) | 약 29% (2위) |

1.2 이벤트 드리븐 아키텍처

Apache (프로세스 모델):

┌────────────┐

│ Master │

├────────────┤

│ Worker 1 │ → Client A (1 process per connection)

│ Worker 2 │ → Client B

│ Worker 3 │ → Client C

│ ... │

│ Worker 1000│ → Client 1000

└────────────┘

→ 1000 connections = 1000 processes/threads = 높은 메모리 사용

Nginx (이벤트 모델):

┌────────────┐

│ Master │

├────────────┤

│ Worker 1 │ → epoll/kqueue로 수천 연결 처리

│ Worker 2 │ → (non-blocking I/O)

│ Worker 3 │ →

│ Worker 4 │ → (CPU 코어 수만큼)

└────────────┘

→ 10000 connections = 4 workers = 매우 낮은 메모리 사용

**핵심 원리:**

- **Master Process**: 설정 읽기, 워커 관리, 로그 관리

- **Worker Process**: 실제 요청 처리 (CPU 코어 수만큼 생성)

- **epoll/kqueue**: OS 레벨의 이벤트 통지 메커니즘

- **Non-blocking I/O**: 요청을 기다리지 않고 다른 요청 처리

1.3 Nginx 설치

Ubuntu/Debian

sudo apt update

sudo apt install nginx

CentOS/RHEL

sudo yum install epel-release

sudo yum install nginx

macOS

brew install nginx

Docker

docker run -d -p 80:80 -p 443:443 \

-v /path/to/nginx.conf:/etc/nginx/nginx.conf:ro \

-v /path/to/certs:/etc/nginx/certs:ro \

--name nginx nginx:alpine

상태 확인

sudo systemctl status nginx

nginx -t # 설정 문법 검사

nginx -V # 컴파일 옵션 확인

2. Nginx 설정 구조

2.1 설정 파일 구조

/etc/nginx/

├── nginx.conf # 메인 설정

├── conf.d/ # 추가 설정 (*.conf 자동 로드)

│ ├── default.conf

│ └── myapp.conf

├── sites-available/ # 사용 가능한 사이트 (Debian계열)

│ └── mysite.conf

├── sites-enabled/ # 활성화된 사이트 (심볼릭 링크)

│ └── mysite.conf -> ../sites-available/mysite.conf

├── mime.types # MIME 타입 매핑

├── fastcgi_params # FastCGI 파라미터

└── snippets/ # 재사용 가능한 설정 조각

├── ssl-params.conf

└── proxy-params.conf

2.2 설정 블록 계층

/etc/nginx/nginx.conf

전역 컨텍스트

user nginx;

worker_processes auto; # CPU 코어 수만큼 자동 설정

worker_rlimit_nofile 65535; # 워커당 최대 파일 디스크립터

error_log /var/log/nginx/error.log warn;

pid /run/nginx.pid;

이벤트 컨텍스트

events {

worker_connections 10240; # 워커당 최대 동시 연결

multi_accept on; # 한 번에 여러 연결 수락

use epoll; # Linux: epoll, BSD: kqueue

}

HTTP 컨텍스트

http {

include /etc/nginx/mime.types;

default_type application/octet-stream;

로그 포맷

log_format main '$remote_addr - $remote_user [$time_local] '

'"$request" $status $body_bytes_sent '

'"$http_referer" "$http_user_agent" '

'$request_time $upstream_response_time';

access_log /var/log/nginx/access.log main;

성능 설정

sendfile on;

tcp_nopush on;

tcp_nodelay on;

keepalive_timeout 65;

types_hash_max_size 2048;

client_max_body_size 50m;

Gzip 압축

gzip on;

gzip_vary on;

gzip_min_length 1024;

gzip_comp_level 5;

gzip_types text/plain text/css application/json

application/javascript text/xml application/xml

application/xml+rss text/javascript image/svg+xml;

서버 블록 포함

include /etc/nginx/conf.d/*.conf;

}

2.3 Server 블록과 Location 블록

server {

listen 80;

listen [::]:80;

server_name example.com www.example.com;

301 리다이렉트 (HTTP → HTTPS)

return 301 https://$server_name$request_uri;

}

server {

listen 443 ssl http2;

listen [::]:443 ssl http2;

server_name example.com www.example.com;

SSL 설정

ssl_certificate /etc/nginx/certs/fullchain.pem;

ssl_certificate_key /etc/nginx/certs/privkey.pem;

루트 디렉토리

root /var/www/html;

index index.html index.htm;

Location 우선순위 (높은 순서)

1. 정확한 일치 (=)

location = /favicon.ico {

log_not_found off;

access_log off;

}

2. 우선 접두사 (^~)

location ^~ /static/ {

alias /var/www/static/;

expires 30d;

add_header Cache-Control "public, immutable";

}

3. 정규식 (~, ~*) - 대소문자 구분/무시

location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {

expires 7d;

add_header Cache-Control "public";

}

4. 접두사 일치 (없음 또는 /)

location / {

try_files $uri $uri/ /index.html;

}

API 프록시

location /api/ {

proxy_pass http://backend;

include snippets/proxy-params.conf;

}

에러 페이지

error_page 404 /404.html;

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root /usr/share/nginx/html;

}

}

2.4 Location 매칭 우선순위

우선순위 (높은 순):

1. = (정확한 일치) location = /path

2. ^~ (우선 접두사) location ^~ /path

3. ~ (정규식, 대소문자 구분) location ~ \.php$

4. ~* (정규식, 대소문자 무시) location ~* \.(jpg|png)$

5. / (접두사 일치) location /path

6. / (기본) location /

3. 리버스 프록시 설정

3.1 기본 리버스 프록시

snippets/proxy-params.conf

proxy_http_version 1.1;

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_set_header Connection "";

proxy_connect_timeout 60s;

proxy_send_timeout 60s;

proxy_read_timeout 60s;

proxy_buffering on;

proxy_buffer_size 4k;

proxy_buffers 8 4k;

proxy_busy_buffers_size 8k;

server {

listen 443 ssl http2;

server_name api.example.com;

ssl_certificate /etc/nginx/certs/fullchain.pem;

ssl_certificate_key /etc/nginx/certs/privkey.pem;

location / {

proxy_pass http://127.0.0.1:3000;

include snippets/proxy-params.conf;

}

}

3.2 프록시 동작 원리

Client Nginx (Reverse Proxy) Backend

│ │ │

│ GET /api/users │ │

│─────────────────────────────>│ │

│ │ GET /api/users │

│ │ Host: api.example.com │

│ │ X-Real-IP: 203.0.113.1 │

│ │ X-Forwarded-For: 203.0.113.1│

│ │─────────────────────────────>│

│ │ │

│ │ 200 OK │

│ │<─────────────────────────────│

│ 200 OK │ │

│<─────────────────────────────│ │

3.3 경로 재작성(Rewrite)

/api/v1/users → 백엔드의 /users로 전달

location /api/v1/ {

rewrite ^/api/v1/(.*)$ /$1 break;

proxy_pass http://backend;

include snippets/proxy-params.conf;

}

또는 proxy_pass에 URI 포함

location /api/v1/ {

proxy_pass http://backend/; # 슬래시 주의!

include snippets/proxy-params.conf;

}

조건부 리다이렉트

location /old-page {

return 301 /new-page;

}

정규식 기반 rewrite

rewrite ^/blog/(\d{4})/(\d{2})/(.*)$ /posts/$3?year=$1&month=$2 permanent;

4. 로드 밸런싱

4.1 Upstream 설정

기본 Round Robin

upstream backend {

server 10.0.0.1:8080;

server 10.0.0.2:8080;

server 10.0.0.3:8080;

}

Least Connections - 가장 적은 연결 수를 가진 서버로

upstream backend_least {

least_conn;

server 10.0.0.1:8080;

server 10.0.0.2:8080;

server 10.0.0.3:8080;

}

IP Hash - 같은 클라이언트 IP는 같은 서버로 (세션 고정)

upstream backend_iphash {

ip_hash;

server 10.0.0.1:8080;

server 10.0.0.2:8080;

server 10.0.0.3:8080;

}

가중치(Weight) 기반

upstream backend_weighted {

server 10.0.0.1:8080 weight=5; # 50% 트래픽

server 10.0.0.2:8080 weight=3; # 30% 트래픽

server 10.0.0.3:8080 weight=2; # 20% 트래픽

}

고급 설정

upstream backend_advanced {

least_conn;

server 10.0.0.1:8080 weight=3 max_fails=3 fail_timeout=30s;

server 10.0.0.2:8080 weight=2 max_fails=3 fail_timeout=30s;

server 10.0.0.3:8080 backup; # 다른 서버 장애 시만 사용

server 10.0.0.4:8080 down; # 일시적으로 비활성화

keepalive 32; # 업스트림 커넥션 풀

}

4.2 로드 밸런싱 알고리즘 비교

| 알고리즘 | 설명 | 장점 | 단점 | 적합한 상황 |

|---------|------|------|------|-----------|

| Round Robin | 순차적 분배 (기본) | 간단, 균등 분배 | 서버 성능 차이 미반영 | 동일 사양 서버 |

| Least Connections | 최소 연결 수 서버로 | 부하 균형 | 새 서버에 집중 가능 | 요청 처리 시간 불균등 |

| IP Hash | 클라이언트 IP 기반 | 세션 고정 | 불균등 분배 가능 | 세션 기반 앱 |

| Weight | 가중치 기반 | 성능 차이 반영 | 수동 관리 | 서버 스펙 차이 |

| Random | 무작위 (Nginx Plus) | 분산 환경 적합 | 예측 불가 | 대규모 클러스터 |

4.3 헬스 체크

패시브 헬스 체크 (OSS)

upstream backend {

server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;

server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;

}

액티브 헬스 체크 (Nginx Plus 또는 별도 모듈)

upstream backend {

zone backend_zone 64k;

server 10.0.0.1:8080;

server 10.0.0.2:8080;

health_check interval=10 fails=3 passes=2 uri=/health;

}

5. SSL/TLS 설정

5.1 Let's Encrypt + Certbot

Certbot 설치 및 인증서 발급

sudo apt install certbot python3-certbot-nginx

sudo certbot --nginx -d example.com -d www.example.com

자동 갱신 확인

sudo certbot renew --dry-run

crontab에 자동 갱신 추가

0 0,12 * * * certbot renew --quiet --post-hook "systemctl reload nginx"

5.2 강화된 SSL 설정

snippets/ssl-params.conf

프로토콜 - TLS 1.2, 1.3만 허용

ssl_protocols TLSv1.2 TLSv1.3;

암호화 스위트

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

ssl_prefer_server_ciphers on;

DH 파라미터

ssl_dhparam /etc/nginx/certs/dhparam.pem;

SSL 세션 캐시

ssl_session_cache shared:SSL:10m;

ssl_session_timeout 1d;

ssl_session_tickets off;

OCSP Stapling

ssl_stapling on;

ssl_stapling_verify on;

ssl_trusted_certificate /etc/nginx/certs/chain.pem;

resolver 1.1.1.1 8.8.8.8 valid=300s;

HSTS (Strict Transport Security)

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

5.3 SSL Termination 패턴

Client (HTTPS) Nginx (SSL Termination) Backend (HTTP)

│ │ │

│ HTTPS (TLS 1.3) │ │

│─────────────────────────>│ │

│ │ HTTP (plain) │

│ │─────────────────────────────>│

│ │ │

│ │ HTTP Response │

│ │<─────────────────────────────│

│ HTTPS Response │ │

│<─────────────────────────│ │

server {

listen 443 ssl http2;

server_name example.com;

ssl_certificate /etc/nginx/certs/fullchain.pem;

ssl_certificate_key /etc/nginx/certs/privkey.pem;

include snippets/ssl-params.conf;

location / {

proxy_pass http://backend;

proxy_set_header X-Forwarded-Proto https;

include snippets/proxy-params.conf;

}

}

6. 캐싱 (Proxy Cache)

6.1 기본 캐시 설정

http {

캐시 존 정의

proxy_cache_path /var/cache/nginx

levels=1:2

keys_zone=my_cache:10m # 10MB 메모리 (키 저장)

max_size=10g # 디스크 최대 크기

inactive=60m # 60분 미사용 시 삭제

use_temp_path=off;

server {

listen 443 ssl http2;

server_name example.com;

캐시 활성화

location /api/ {

proxy_cache my_cache;

proxy_cache_valid 200 302 10m; # 200, 302 응답 10분

proxy_cache_valid 404 1m; # 404 응답 1분

proxy_cache_use_stale error timeout updating

http_500 http_502 http_503 http_504;

proxy_cache_background_update on;

proxy_cache_lock on;

캐시 키 설정

proxy_cache_key "$scheme$request_method$host$request_uri";

캐시 상태 헤더 추가

add_header X-Cache-Status $upstream_cache_status;

proxy_pass http://backend;

include snippets/proxy-params.conf;

}

정적 파일 캐시 (브라우저)

location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {

root /var/www/static;

expires 30d;

add_header Cache-Control "public, immutable";

access_log off;

}

}

}

6.2 캐시 상태 값

| 상태 | 설명 |

|------|------|

| `HIT` | 캐시에서 응답 제공 |

| `MISS` | 캐시 없음, 백엔드에서 가져옴 |

| `EXPIRED` | 캐시 만료, 백엔드에서 갱신 |

| `STALE` | 만료된 캐시이지만 stale 정책으로 제공 |

| `UPDATING` | stale 응답 제공 중, 백그라운드 갱신 |

| `REVALIDATED` | 백엔드가 304 응답, 기존 캐시 재사용 |

| `BYPASS` | 캐시 무시 설정으로 백엔드 직접 요청 |

6.3 캐시 바이패스와 퍼지

특정 조건에서 캐시 무시

location /api/ {

proxy_cache my_cache;

쿠키가 있으면 캐시 안 함

proxy_cache_bypass $cookie_session;

proxy_no_cache $cookie_session;

Cache-Control: no-cache 요청 시 캐시 무시

proxy_cache_bypass $http_cache_control;

특정 쿼리 파라미터로 캐시 퍼지

proxy_cache_purge $purge_method; # Nginx Plus

proxy_pass http://backend;

}

7. Rate Limiting (속도 제한)

7.1 기본 Rate Limiting

http {

제한 존 정의

10MB 메모리, IP당 초당 10 요청

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

IP당 초당 1 요청 (로그인 보호)

limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;

API 키 기반 제한

limit_req_zone $http_x_api_key zone=apikey_limit:10m rate=100r/s;

server {

API 엔드포인트 - 버스트 허용

location /api/ {

limit_req zone=api_limit burst=20 nodelay;

limit_req_status 429;

proxy_pass http://backend;

}

로그인 - 엄격한 제한

location /auth/login {

limit_req zone=login_limit burst=5;

limit_req_status 429;

proxy_pass http://backend;

}

}

}

7.2 연결 수 제한

http {

IP당 동시 연결 수 제한

limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {

IP당 최대 100 동시 연결

limit_conn conn_limit 100;

다운로드 대역폭 제한

location /downloads/ {

limit_conn conn_limit 5; # 5개 동시 다운로드

limit_rate 500k; # 연결당 500KB/s

limit_rate_after 10m; # 처음 10MB는 제한 없음

}

}

}

7.3 Rate Limiting 동작 이해

rate=10r/s, burst=20, nodelay:

시간 │ 요청수 │ 처리 │ 설명

─────│───────│─────│──────────────────────────────

0.0s │ 25 │ 21 │ 10(rate) + 20(burst) = 30까지 허용

│ │ │ 21개 즉시 처리, 4개 429 응답

0.1s │ 5 │ 1 │ burst 버킷에 1개 여유 (0.1s * 10r/s = 1)

1.0s │ 5 │ 5 │ burst 버킷이 10개 회복

8. WebSocket 프록시

8.1 WebSocket 설정

WebSocket 업그레이드를 위한 map

map $http_upgrade $connection_upgrade {

default upgrade;

'' close;

}

upstream websocket_backend {

server 10.0.0.1:8080;

server 10.0.0.2:8080;

WebSocket은 sticky session 필요

ip_hash;

}

server {

listen 443 ssl http2;

server_name ws.example.com;

ssl_certificate /etc/nginx/certs/fullchain.pem;

ssl_certificate_key /etc/nginx/certs/privkey.pem;

location /ws/ {

proxy_pass http://websocket_backend;

proxy_http_version 1.1;

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection $connection_upgrade;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

WebSocket 타임아웃 (기본 60초)

proxy_read_timeout 3600s;

proxy_send_timeout 3600s;

}

}

8.2 WebSocket 핸드셰이크 흐름

Client Nginx Backend

│ │ │

│ GET /ws/ HTTP/1.1 │ │

│ Upgrade: websocket │ │

│ Connection: Upgrade │ │

│────────────────────────>│ │

│ │ GET /ws/ HTTP/1.1 │

│ │ Upgrade: websocket │

│ │ Connection: Upgrade │

│ │────────────────────────>│

│ │ │

│ │ 101 Switching Protocols │

│ │<────────────────────────│

│ 101 Switching Protocols │ │

│<────────────────────────│ │

│ │ │

│ ← WebSocket frames → │ ← WebSocket frames → │

9. 보안 설정

9.1 보안 헤더

server {

XSS 보호

add_header X-XSS-Protection "1; mode=block" always;

MIME 타입 스니핑 방지

add_header X-Content-Type-Options "nosniff" always;

클릭재킹 방지

add_header X-Frame-Options "SAMEORIGIN" always;

Referrer 정책

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Content Security Policy

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: cdn.example.com; font-src 'self' fonts.gstatic.com;" always;

Permissions Policy

add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

}

9.2 접근 제어

server {

IP 기반 접근 제어

location /admin/ {

allow 10.0.0.0/8;

allow 192.168.0.0/16;

deny all;

proxy_pass http://backend;

}

Basic Authentication

location /internal/ {

auth_basic "Restricted Access";

auth_basic_user_file /etc/nginx/.htpasswd;

proxy_pass http://backend;

}

특정 HTTP 메서드만 허용

location /api/ {

limit_except GET POST PUT DELETE {

deny all;

}

proxy_pass http://backend;

}

서버 정보 숨기기

server_tokens off;

숨겨진 파일 접근 차단

location ~ /\. {

deny all;

access_log off;

log_not_found off;

}

}

9.3 DDoS 방어 기본 설정

http {

연결 제한

limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;

limit_req_zone $binary_remote_addr zone=req_per_ip:10m rate=30r/s;

요청 본문 크기 제한

client_max_body_size 10m;

client_body_buffer_size 128k;

client_header_buffer_size 1k;

large_client_header_buffers 4 4k;

타임아웃 설정

client_body_timeout 12;

client_header_timeout 12;

send_timeout 10;

server {

limit_conn conn_per_ip 50;

limit_req zone=req_per_ip burst=50 nodelay;

User-Agent 기반 봇 차단

if ($http_user_agent ~* (bot|crawler|spider|scraper)) {

return 403;

}

빈 User-Agent 차단

if ($http_user_agent = "") {

return 403;

}

}

}

10. Gzip 압축과 성능 최적화

10.1 Gzip 상세 설정

http {

gzip on;

gzip_vary on;

gzip_proxied any;

gzip_comp_level 5; # 1-9 (5가 최적 밸런스)

gzip_min_length 1024; # 1KB 이하는 압축 안 함

gzip_buffers 16 8k;

gzip_http_version 1.1;

gzip_types

text/plain

text/css

text/xml

text/javascript

application/json

application/javascript

application/xml

application/xml+rss

application/atom+xml

image/svg+xml

font/opentype

font/ttf

font/woff

font/woff2;

미리 압축된 파일 사용 (빌드 시 생성)

gzip_static on;

}

10.2 Brotli 압축 (Nginx 모듈)

Brotli는 Gzip보다 20-30% 더 효율적

별도 모듈 설치 필요

load_module modules/ngx_http_brotli_filter_module.so;

load_module modules/ngx_http_brotli_static_module.so;

http {

brotli on;

brotli_comp_level 6;

brotli_types text/plain text/css application/json

application/javascript text/xml application/xml

application/xml+rss text/javascript image/svg+xml;

brotli_static on;

}

10.3 성능 튜닝 체크리스트

/etc/nginx/nginx.conf

worker_processes auto; # CPU 코어 수

worker_rlimit_nofile 65535;

events {

worker_connections 10240;

multi_accept on;

use epoll;

}

http {

파일 전송 최적화

sendfile on;

tcp_nopush on; # sendfile과 함께 사용

tcp_nodelay on; # keepalive에서 유효

타임아웃

keepalive_timeout 65;

keepalive_requests 1000;

버퍼

client_body_buffer_size 16k;

client_header_buffer_size 1k;

client_max_body_size 50m;

large_client_header_buffers 4 8k;

파일 캐시

open_file_cache max=10000 inactive=20s;

open_file_cache_valid 30s;

open_file_cache_min_uses 2;

open_file_cache_errors on;

업스트림 커넥션 풀

upstream backend {

keepalive 32;

keepalive_requests 100;

keepalive_timeout 60s;

}

}

11. Docker & Kubernetes 연동

11.1 Docker Compose로 Nginx 구성

docker-compose.yml

version: '3.8'

services:

nginx:

image: nginx:alpine

ports:

- "80:80"

- "443:443"

volumes:

- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro

- ./nginx/conf.d:/etc/nginx/conf.d:ro

- ./nginx/certs:/etc/nginx/certs:ro

- ./nginx/cache:/var/cache/nginx

depends_on:

- app1

- app2

networks:

- webnet

restart: unless-stopped

deploy:

resources:

limits:

cpus: '2'

memory: 512M

app1:

image: myapp:latest

expose:

- "3000"

networks:

- webnet

app2:

image: myapp:latest

expose:

- "3000"

networks:

- webnet

networks:

webnet:

driver: bridge

nginx/conf.d/default.conf

upstream app {

server app1:3000;

server app2:3000;

keepalive 16;

}

server {

listen 80;

server_name _;

return 301 https://$host$request_uri;

}

server {

listen 443 ssl http2;

server_name example.com;

ssl_certificate /etc/nginx/certs/fullchain.pem;

ssl_certificate_key /etc/nginx/certs/privkey.pem;

location / {

proxy_pass http://app;

include /etc/nginx/snippets/proxy-params.conf;

}

}

11.2 Kubernetes Ingress (Nginx Ingress Controller)

Nginx Ingress Controller 설치

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.0/deploy/static/provider/cloud/deploy.yaml

Ingress 리소스 정의

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: my-app-ingress

annotations:

nginx.ingress.kubernetes.io/rewrite-target: /

nginx.ingress.kubernetes.io/ssl-redirect: "true"

nginx.ingress.kubernetes.io/rate-limit: "10"

nginx.ingress.kubernetes.io/rate-limit-window: "1m"

nginx.ingress.kubernetes.io/proxy-body-size: "50m"

nginx.ingress.kubernetes.io/proxy-read-timeout: "60"

nginx.ingress.kubernetes.io/proxy-send-timeout: "60"

cert-manager.io/cluster-issuer: "letsencrypt-prod"

spec:

ingressClassName: nginx

tls:

- hosts:

- example.com

- api.example.com

secretName: example-tls

rules:

- host: example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: frontend-svc

port:

number: 80

- host: api.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: backend-svc

port:

number: 8080

12. Nginx vs Traefik vs Caddy 비교

| 기능 | Nginx | Traefik | Caddy |

|------|-------|---------|-------|

| 설정 방식 | 파일 기반 | 동적 (Docker Label, K8s) | Caddyfile / JSON API |

| 자동 HTTPS | 수동 (Certbot) | 내장 (ACME) | 내장 (ACME) |

| 서비스 디스커버리 | 수동 | Docker/K8s 자동 | 제한적 |

| 성능 | 최고 수준 | 좋음 | 좋음 |

| HTTP/3 | 모듈로 지원 | 내장 | 내장 |

| 대시보드 | 없음 (Nginx Plus 유료) | 내장 웹 UI | 내장 API |

| 설정 리로드 | `nginx -s reload` | 자동 핫 리로드 | 자동 핫 리로드 |

| 커뮤니티 | 매우 큼 | 성장 중 | 성장 중 |

| 적합 환경 | 범용, 고성능 | 마이크로서비스, Docker | 소규모, 간편 설정 |

| 라이선스 | BSD | MIT | Apache 2.0 |

12.1 선택 가이드

**Nginx를 선택해야 할 때:**

- 최고의 성능과 안정성이 필요할 때

- 복잡한 리버스 프록시 규칙이 필요할 때

- 레거시 시스템이나 정적 파일 서빙에 최적

- 큰 커뮤니티와 풍부한 문서가 필요할 때

**Traefik을 선택해야 할 때:**

- Docker/Kubernetes 환경에서 자동 서비스 디스커버리가 필요할 때

- 동적으로 라우팅 규칙이 변경되는 마이크로서비스 환경

- 내장 대시보드와 메트릭이 필요할 때

**Caddy를 선택해야 할 때:**

- 자동 HTTPS가 가장 중요할 때

- 간단한 설정으로 빠르게 시작하고 싶을 때

- 소규모 프로젝트나 개발 환경

13. 면접 대비 퀴즈

Apache의 전통적인 Prefork/Worker MPM은 각 연결마다 프로세스나 스레드를 할당합니다. 10,000개의 동시 연결이면 10,000개의 프로세스/스레드가 필요하며, 각각 수 MB의 메모리를 소비합니다.

Nginx는 이벤트 루프 기반으로 동작하여 소수의 Worker Process(보통 CPU 코어 수)가 epoll/kqueue 같은 OS 이벤트 메커니즘을 통해 수만 개의 연결을 비동기적으로 처리합니다.

**핵심 차이:**

- 메모리 효율성: Nginx는 연결당 수 KB vs Apache는 연결당 수 MB

- 컨텍스트 스위칭: Nginx는 최소화 vs Apache는 프로세스/스레드 전환 오버헤드

- C10K 문제: Nginx는 설계 단계부터 이 문제를 해결하기 위해 만들어짐

- 단, CPU 집약적인 작업에는 이벤트 모델이 불리할 수 있음

이것은 Nginx 설정에서 가장 흔한 실수 중 하나입니다.

`proxy_pass http://backend;` (슬래시 없음):

요청 URI가 그대로 전달됩니다. `/api/users` 요청은 백엔드에 `/api/users`로 전달됩니다.

`proxy_pass http://backend/;` (슬래시 있음):

location에 매칭된 부분이 제거되고 나머지가 전달됩니다.

예시 - `location /api/`에서:

- 슬래시 없음: `/api/users` 요청은 `http://backend/api/users`로 전달

- 슬래시 있음: `/api/users` 요청은 `http://backend/users`로 전달

이 차이를 이해하지 못하면 404 에러나 잘못된 라우팅이 발생합니다.

`limit_req zone=api rate=10r/s burst=20 nodelay;`

**rate=10r/s**: 초당 10개 요청까지 허용합니다. 내부적으로 100ms마다 1개 요청을 허용하는 토큰 버킷 방식입니다.

**burst=20**: rate를 초과하는 요청을 최대 20개까지 큐에 대기시킵니다. burst 없이는 rate 초과 시 즉시 429 응답입니다.

**nodelay**: burst 큐에 들어온 요청을 지연 없이 즉시 처리합니다. nodelay 없이는 요청이 rate에 맞춰 순차적으로 처리되므로 대기 시간이 발생합니다.

**조합 효과:**

- `rate=10r/s burst=20`: 순간 최대 21개 처리 가능하지만, burst 요청은 지연됨

- `rate=10r/s burst=20 nodelay`: 순간 최대 21개를 즉시 처리, 초과분은 429

SSL Termination(SSL 종료)은 HTTPS 암호화/복호화를 Nginx(리버스 프록시)에서 처리하고, 백엔드 서버에는 일반 HTTP로 통신하는 패턴입니다.

**장점:**

1. **백엔드 부하 감소**: SSL 핸드셰이크와 암복호화는 CPU 집약적 작업. 이를 Nginx에 집중시킴

2. **인증서 관리 중앙화**: 모든 인증서를 Nginx 한 곳에서 관리

3. **백엔드 단순화**: 백엔드 애플리케이션이 SSL을 신경 쓰지 않아도 됨

4. **성능 최적화**: Nginx의 SSL 세션 캐시, OCSP Stapling 등 활용

**보안 고려사항:**

- Nginx와 백엔드 사이의 내부 네트워크가 안전해야 함

- 필요시 내부 통신에도 mTLS(Mutual TLS) 적용 가능

- `X-Forwarded-Proto` 헤더로 백엔드에 원본 프로토콜 전달

`keepalive`는 Nginx와 업스트림(백엔드) 서버 간의 유휴(idle) 연결을 캐시하는 커넥션 풀입니다.

upstream backend {

server 10.0.0.1:8080;

server 10.0.0.2:8080;

keepalive 32;

}

**keepalive가 없으면:**

매 요청마다 TCP 3-way handshake가 발생합니다. 고부하 시 TIME_WAIT 상태의 소켓이 급증하여 포트 고갈이 발생할 수 있습니다.

**keepalive가 있으면:**

이전 연결을 재사용하여 TCP 핸드셰이크 오버헤드를 제거합니다. 지연 시간 감소와 처리량 증가 효과가 있습니다.

**적절한 값:**

- 동시 연결 수의 약 2배가 시작점

- 너무 높으면 메모리 낭비, 너무 낮으면 커넥션 재사용 효과 감소

- `proxy_http_version 1.1;`과 `proxy_set_header Connection "";`을 함께 설정해야 작동

14. 참고 자료

1. [Nginx 공식 문서](https://nginx.org/en/docs/)

2. [Nginx Admin Guide](https://docs.nginx.com/nginx/admin-guide/)

3. [Nginx Plus 기능 비교](https://www.nginx.com/products/nginx/)

4. [Let's Encrypt / Certbot](https://certbot.eff.org/)

5. [Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/)

6. [Traefik 공식 문서](https://doc.traefik.io/traefik/)

7. [Caddy 공식 문서](https://caddyserver.com/docs/)

8. [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/)

9. [Nginx 성능 튜닝 가이드](https://www.nginx.com/blog/tuning-nginx/)

10. [C10K Problem](http://www.kegel.com/c10k.html)

11. [Nginx Cookbook (O'Reilly)](https://www.oreilly.com/library/view/nginx-cookbook/9781492078470/)

12. [DigitalOcean Nginx 튜토리얼](https://www.digitalocean.com/community/tags/nginx)

13. [Nginx Security Best Practices](https://docs.nginx.com/nginx/admin-guide/security-controls/)

현재 단락 (1/698)

Nginx(엔진엑스)는 2004년 Igor Sysoev가 C10K 문제를 해결하기 위해 개발한 고성능 웹 서버입니다. 현재 전 세계 웹 서버 시장 점유율 1위를 차지하며, 단순 웹...

작성 글자: 0원문 글자: 19,503작성 단락: 0/698