리버스 프록시 (Reverse Proxy)
클라이언트 요청을 받아서 백엔드 서버(들)로 전달하고, 응답을 돌려주는 중개 서버. HTTPS/SSL 종료, 로드 밸런싱, 요청 라우팅을 담당.
설명
정방향 프록시 vs 리버스 프록시
정방향 프록시 (Forward Proxy):
클라이언트 → [프록시] → 인터넷(외부 서버)
클라이언트 IP 숨기기, 캐싱, 필터링 (회사 방화벽)
리버스 프록시 (Reverse Proxy):
인터넷(클라이언트) → [프록시] → 백엔드 서버들
서버 IP 숨기기, 로드 밸런싱, SSL/TLS 종료, 라우팅
리버스 프록시의 3대 역할
1. HTTPS/SSL 종료 (SSL Termination)
클라이언트 ─(HTTPS 443)─ [리버스 프록시] ─(HTTP 8000)─ FastAPI
↑
SSL/TLS 인증서 관리
이점:
- 백엔드 서버는 HTTP만 처리 (복잡성 감소)
- 중앙화된 인증서 관리
- Let’s Encrypt 자동 갱신 (Traefik)
2. 로드 밸런싱 (Load Balancing)
클라이언트 요청
↓
[리버스 프록시: 라운드로빈]
├─ FastAPI 인스턴스 1 (8000)
├─ FastAPI 인스턴스 2 (8000)
└─ FastAPI 인스턴스 3 (8000)
알고리즘:
- 라운드로빈: 순서대로 분배 (1번 → 2번 → 3번 → 1번…)
- 최소 연결: 활성 연결이 가장 적은 서버 선택
- IP 해시: 같은 클라이언트 → 같은 서버 (세션 일관성)
효과: 단일 인스턴스보다 동시성 ~N배 증가
3. HTTP 라우팅 (Request Routing)
Nginx 설정:
location /api/ → app1:8000
location /static/ → 정적 파일 서버
location /auth/ → app2:8000
경로·호스트·헤더 기반 라우팅.
Traefik vs Nginx
Traefik (자동화 우선)
# Docker Compose: 레이블 기반 자동 설정
labels:
- "traefik.http.routers.fastapi.rule=Host(`yourdomain.com`)"
- "traefik.http.routers.fastapi.tls.certresolver=letsencrypt"장점:
- Let’s Encrypt 내장 (인증서 자동 갱신)
- Docker 레이블로 자동 발견
- 설정 변경 시 재시작 불필요
단점:
- 성능: Nginx보다 약간 느림
- 메모리: 더 많이 사용
Nginx (경량·성능)
upstream fastapi {
server app1:8000;
server app2:8000;
}
server {
listen 443 ssl;
location / {
proxy_pass http://fastapi;
}
}장점:
- 성능: 매우 빠름, 메모리 효율적
- 세밀한 설정 제어
단점:
- Let’s Encrypt는 Certbot 별도 필요
- 설정 변경 시 재로드 필요
프로덕션 아키텍처
┌─────────────────────────────────────┐
│ 클라이언트 (인터넷) │
└──────────────────┬──────────────────┘
│ (HTTPS 443)
┌─────────▼──────────┐
│ 리버스 프록시 │
│ (Traefik/Nginx) │
│ ✓ SSL/TLS 인증서 │
│ ✓ 로드 밸런싱 │
└────┬────┬────┬────┘
│ │ │ (HTTP 8000)
┌─────▼─┐ │ ┌─┴────┐
│ App 1 │ │ │ App 3 │
└───────┘ │ └───────┘
┌────▼─────┐
│ App 2 │
└──────────┘
특징:
- 리버스 프록시가 공인 IP (0.0.0.0:443)에 바인드
- 백엔드 서버는 내부 네트워크 (app1:8000, app2:8000 등)
- 클라이언트는 백엔드 직접 접근 불가 (IP 숨김)
헤더 전달 (Header Forwarding)
리버스 프록시는 클라이언트 정보를 X-Forwarded-* 헤더로 전달:
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; # http 또는 https백엔드 앱이 원본 클라이언트 IP/프로토콜 인식 가능:
@app.get("/client-info")
def get_client_info(request: Request):
client_ip = request.headers.get('X-Real-IP')
protocol = request.headers.get('X-Forwarded-Proto')
return {"ip": client_ip, "protocol": protocol}설정 예시
Traefik (개발)
[entryPoints.http]
address = ":80"
[providers.docker]
exposedByDefault = falseDocker 레이블로 자동 설정.
Traefik (프로덕션)
[entryPoints.http]
address = ":80"
[entryPoints.http.http.redirections.entryPoint]
to = "https" # 80 → 443 리다이렉트
[entryPoints.https]
address = ":443"
[entryPoints.https.http.tls]
certResolver = "letsencrypt"
[certificatesResolvers.letsencrypt.acme]
email = "admin@example.com"
storage = "acme.json"
[certificatesResolvers.letsencrypt.acme.httpChallenge]
entryPoint = "http"Let’s Encrypt 자동화.
Nginx (기본)
upstream backend {
least_conn;
server app1:8000;
server app2:8000;
server app3:8000;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://backend;
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;
}
}
# HTTP → HTTPS 리다이렉트
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}관련 개념
- containerization — 여러 컨테이너 앞에 배치
- structured-logging — 로드 밸런싱 후 로그 수집
실전 적용
traefik 의 적용
- Docker 레이블 기반 자동 라우팅
- Let’s Encrypt 인증서 자동화
nginx 의 적용
- 경량 성능 중심 로드 밸런싱
- 세밀한 설정 제어
fastapi 앞단
- HTTPS/SSL 종료
- 여러 FastAPI 인스턴스 로드 밸런싱