리버스 프록시와 API 게이트웨이

리버스 프록시와 API 게이트웨이

개요

이 문서에서는 리버스 프록시의 역할과 API 게이트웨이 패턴을 다룹니다. SSL 종료, 압축, 캐싱 등 리버스 프록시의 핵심 기능과 인증/인가, 라우팅, Rate Limiting 알고리즘을 학습합니다.

난이도: ⭐⭐⭐ 예상 학습 시간: 2-3시간 선수 지식: 04_Load_Balancing.md


목차

  1. 리버스 프록시란?
  2. 리버스 프록시 핵심 기능
  3. API 게이트웨이 패턴
  4. Rate Limiting
  5. 연습 문제
  6. 다음 단계
  7. 참고 자료

1. 리버스 프록시란?

1.1 Forward Proxy vs Reverse Proxy

┌─────────────────────────────────────────────────────────────────┐
│              Forward Proxy vs Reverse Proxy                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Forward Proxy (정방향 프록시)                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  "클라이언트를 대신하여 서버에 요청"                       │ │
│  │                                                            │ │
│  │  ┌──────┐    ┌──────────┐    ┌──────────┐                  │ │
│  │  │Client│───▶│ Forward  │───▶│  Server  │                  │ │
│  │  │      │    │ Proxy    │    │  (Web)   │                  │ │
│  │  └──────┘    └──────────┘    └──────────┘                  │ │
│  │                                                            │ │
│  │  용도: 익명성, 접근 제어, 캐싱                             │ │
│  │  예: 회사 방화벽, VPN, Squid                               │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  Reverse Proxy (역방향 프록시)                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  "서버를 대신하여 클라이언트 요청을 처리"                  │ │
│  │                                                            │ │
│  │  ┌──────┐    ┌──────────┐    ┌──────────┐                  │ │
│  │  │Client│───▶│ Reverse  │───▶│ Backend  │                  │ │
│  │  │      │    │ Proxy    │    │ Servers  │                  │ │
│  │  └──────┘    └──────────┘    └──────────┘                  │ │
│  │                                                            │ │
│  │  클라이언트는 실제 서버를 모름!                            │ │
│  │                                                            │ │
│  │  용도: 로드밸런싱, SSL 종료, 캐싱, 보안                    │ │
│  │  예: Nginx, HAProxy, AWS ALB                               │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

1.2 리버스 프록시 위치

┌─────────────────────────────────────────────────────────────────┐
│                   리버스 프록시 아키텍처                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│                         Internet                                 │
│                            │                                     │
│                            ▼                                     │
│                    ┌──────────────┐                              │
│                    │   Firewall   │                              │
│                    └──────┬───────┘                              │
│                           │                                      │
│                           ▼                                      │
│                    ┌──────────────┐                              │
│                    │   Reverse    │ ◀── SSL 종료, 캐싱          │
│                    │   Proxy      │     압축, 보안               │
│                    │   (Nginx)    │                              │
│                    └──────┬───────┘                              │
│                           │                                      │
│              ┌────────────┼────────────┐                         │
│              │            │            │                         │
│              ▼            ▼            ▼                         │
│         ┌────────┐   ┌────────┐   ┌────────┐                    │
│         │ App    │   │ App    │   │ App    │                    │
│         │ Server │   │ Server │   │ Server │                    │
│         │   1    │   │   2    │   │   3    │                    │
│         └────────┘   └────────┘   └────────┘                    │
│                                                                  │
│  클라이언트 → 프록시 IP만 알고, 실제 서버 IP 모름               │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2. 리버스 프록시 핵심 기능

2.1 SSL/TLS 종료 (SSL Termination)

┌─────────────────────────────────────────────────────────────────┐
                     SSL 종료                                     
├─────────────────────────────────────────────────────────────────┤
                                                                  
  SSL 종료 없이 (End-to-End Encryption):                         
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    Client ═══HTTPS═══▶ Proxy ═══HTTPS═══▶ Server             
                                                               
     모든 서버에 인증서 설치 필요                             
     서버 부하 증가 (암호화/복호화)                           
     인증서 관리 복잡                                         
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  SSL 종료 (프록시에서 처리):                                    
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    Client ═══HTTPS═══▶ Proxy ───HTTP───▶ Server              
                                                              
                     SSL 종료                                  
                                                               
     인증서는 프록시에만 설치                                 
     서버 부하 감소                                           
     중앙 집중식 인증서 관리                                  
                                                               
    Nginx 설정:                                                
    server {                                                   
        listen 443 ssl;                                        
        ssl_certificate /path/to/cert.pem;                     
        ssl_certificate_key /path/to/key.pem;                  
                                                               
        location / {                                           
            proxy_pass http://backend;  # HTTP로 백엔드 연결   
        }                                                      
    }                                                          
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  주의: 내부 네트워크가 신뢰할  없으면 SSL Passthrough 고려    
                                                                  
└─────────────────────────────────────────────────────────────────┘

2.2 응답 압축

┌─────────────────────────────────────────────────────────────────┐
                      응답 압축                                   
├─────────────────────────────────────────────────────────────────┤
                                                                  
  "네트워크 대역폭 절약, 응답 속도 향상"                         
                                                                  
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    압축 : 100KB HTML                                        
    압축 : 20KB (gzip)  80% 절약!                           
                                                               
    Client                Proxy              Server            
                                                            
      │──Request ──────────▶│                                 
        Accept-Encoding:   │──────────────────▶               
        gzip, deflate                                       
                           │◀─────────────────│               
                             원본 응답                      
                             (100KB)                        
                                                            
      │◀── 압축 응답 ───────│                                 
        Content-Encoding:    (프록시에서                    
        gzip                  gzip 압축)                    
        (20KB)                                              
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  Nginx 설정:                                                    
  ┌────────────────────────────────────────────────────────────┐ 
    gzip on;                                                   
    gzip_types text/plain text/css application/json           
               application/javascript text/xml;                
    gzip_min_length 1000;  # 1KB 이상만 압축                   
    gzip_comp_level 6;     # 압축 레벨 (1-9)                   
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  압축 알고리즘 비교:                                            
   gzip: 널리 지원, 좋은 압축률                                 
   Brotli:  나은 압축률, 현대 브라우저 지원                   
   zstd: 빠른 압축/해제, 최신                                   
                                                                  
└─────────────────────────────────────────────────────────────────┘

2.3 캐싱

┌─────────────────────────────────────────────────────────────────┐
                    프록시 캐싱                                   
├─────────────────────────────────────────────────────────────────┤
                                                                  
  "반복 요청에 대해 캐시된 응답 반환"                            
                                                                  
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
     번째 요청 (Cache Miss):                                 
                                                               
    Client ──▶ Proxy ──▶ Server                                
           ◀────────◀────  (응답 저장)                         
                                                              
                [Cache]                                        
                                                               
     번째 요청 (Cache Hit):                                  
                                                               
    Client ──▶ Proxy                                           
           ◀────  (캐시에서 응답, 서버  !)                 
                                                              
            [Cache]                                            
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  Nginx 캐싱 설정:                                               
  ┌────────────────────────────────────────────────────────────┐ 
    # 캐시 경로 정의                                           
    proxy_cache_path /var/cache/nginx levels=1:2               
                     keys_zone=my_cache:10m                    
                     max_size=10g inactive=60m;                
                                                               
    server {                                                   
        location / {                                           
            proxy_cache my_cache;                              
            proxy_cache_valid 200 60m;  # 200 응답 60 캐시   
            proxy_cache_valid 404 1m;   # 404 응답 1 캐시    
            proxy_cache_use_stale error timeout;               
            add_header X-Cache-Status $upstream_cache_status;  
            proxy_pass http://backend;                         
        }                                                      
    }                                                          
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  캐시 상태 헤더:                                                
   X-Cache-Status: HIT (캐시 적중)                              
   X-Cache-Status: MISS (캐시 미스)                             
   X-Cache-Status: EXPIRED (만료됨)                             
   X-Cache-Status: STALE (오래된 캐시 사용)                     
                                                                  
└─────────────────────────────────────────────────────────────────┘

2.4 보안 기능

┌─────────────────────────────────────────────────────────────────┐
                   리버스 프록시 보안 기능                        
├─────────────────────────────────────────────────────────────────┤
                                                                  
  1. IP 기반 접근 제어                                           
  ┌────────────────────────────────────────────────────────────┐ 
    location /admin {                                          
        allow 10.0.0.0/8;       # 내부 네트워크만 허용         
        allow 192.168.1.100;    # 특정 IP 허용                 
        deny all;               # 나머지 거부                  
        proxy_pass http://backend;                             
    }                                                          
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  2. 헤더 보안                                                   
  ┌────────────────────────────────────────────────────────────┐ 
    # 민감한 헤더 숨기기                                       
    proxy_hide_header X-Powered-By;                            
    proxy_hide_header Server;                                  
                                                               
    # 보안 헤더 추가                                           
    add_header X-Frame-Options "SAMEORIGIN";                   
    add_header X-Content-Type-Options "nosniff";               
    add_header X-XSS-Protection "1; mode=block";               
    add_header Strict-Transport-Security "max-age=31536000";   
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  3. 요청 크기 제한                                              
  ┌────────────────────────────────────────────────────────────┐ 
    client_max_body_size 10m;    # 최대 업로드 크기            
    client_body_timeout 60s;     # 요청 본문 타임아웃          
    client_header_timeout 60s;   # 헤더 타임아웃               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  4. 백엔드 서버 숨기기                                          
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    클라이언트가 보는 : proxy.example.com                    
    실제 백엔드: 10.0.1.5:8080 (외부 노출  )               
                                                               
     직접 공격 방지                                           
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
└─────────────────────────────────────────────────────────────────┘

3. API 게이트웨이 패턴

3.1 API 게이트웨이란?

┌─────────────────────────────────────────────────────────────────┐
│                    API 게이트웨이                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "마이크로서비스의 단일 진입점 (Single Entry Point)"            │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  API 게이트웨이 없이:                                      │ │
│  │                                                            │ │
│  │  Client ──▶ User Service (users.example.com)               │ │
│  │         ──▶ Order Service (orders.example.com)             │ │
│  │         ──▶ Product Service (products.example.com)         │ │
│  │                                                            │ │
│  │  문제:                                                     │ │
│  │  • 클라이언트가 여러 서비스 URL 알아야 함                  │ │
│  │  • 각 서비스마다 인증 로직 중복                            │ │
│  │  • 클라이언트-서비스 강결합                                │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  API 게이트웨이 적용:                                      │ │
│  │                                                            │ │
│  │            ┌───────────────────────────────┐               │ │
│  │            │         API Gateway           │               │ │
│  │  Client ──▶│  api.example.com              │               │ │
│  │            │  ┌─────────────────────────┐  │               │ │
│  │            │  │ • 인증/인가            │  │               │ │
│  │            │  │ • 라우팅               │  │               │ │
│  │            │  │ • Rate Limiting        │  │               │ │
│  │            │  │ • 요청/응답 변환       │  │               │ │
│  │            │  │ • 로깅/모니터링        │  │               │ │
│  │            │  └─────────────────────────┘  │               │ │
│  │            └───────────────┬───────────────┘               │ │
│  │                            │                               │ │
│  │              ┌─────────────┼─────────────┐                 │ │
│  │              ▼             ▼             ▼                 │ │
│  │         User Service  Order Service  Product Service      │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

3.2 API 게이트웨이 핵심 기능

┌─────────────────────────────────────────────────────────────────┐
                 API 게이트웨이 핵심 기능                         
├─────────────────────────────────────────────────────────────────┤
                                                                  
  1. 요청 라우팅                                                 
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    /api/users/*    ──────────▶ User Service                   
    /api/orders/*   ──────────▶ Order Service                  
    /api/products/* ──────────▶ Product Service                
    /api/v2/*       ──────────▶ New Service (버전 관리)        
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  2. 인증/인가 (Authentication/Authorization)                    
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    Client ──▶ Gateway                                         
                                                              
                ├─ JWT 토큰 검증                                
                ├─ API Key 확인                                 
                ├─ OAuth2 처리                                  
                └─ 권한 확인  ──▶ Backend Service             
                                                               
    장점: 백엔드 서비스에서 인증 로직 제거                     
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  3. 요청/응답 변환                                              
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
    Protocol 변환:                                             
    REST (외부) ←─────────▶ gRPC (내부)                        
                                                               
    데이터 형식 변환:                                          
    JSON ←─────────▶ Protobuf                                  
                                                               
    응답 집계 (Aggregation):                                   
    ┌────────────────────────────────────────────────────┐    
      GET /api/dashboard                                    
                                                           
           ├──▶ User Service (사용자 정보)                  
           ├──▶ Order Service (최근 주문)                   
           └──▶ Stats Service (통계)                        
                                                            
           ◀── 모든 응답 합쳐서 반환 ──                     
    └────────────────────────────────────────────────────┘    
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
  4. 로깅  모니터링                                            
  ┌────────────────────────────────────────────────────────────┐ 
                                                               
     모든 API 호출 로깅                                       
     응답 시간 측정                                           
     에러율 모니터링                                          
     분산 트레이싱 (Trace ID 전파)                            
                                                               
  └────────────────────────────────────────────────────────────┘ 
                                                                  
└─────────────────────────────────────────────────────────────────┘

3.3 API 게이트웨이 제품 비교

┌─────────────────────────────────────────────────────────────────┐
│                API 게이트웨이 제품 비교                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Kong                                                           │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ • Nginx + Lua 기반                                         │ │
│  │ • 풍부한 플러그인 에코시스템                               │ │
│  │ • 오픈소스 / Enterprise                                    │ │
│  │ • 높은 성능                                                │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  AWS API Gateway                                                │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ • 완전 관리형                                              │ │
│  │ • Lambda, DynamoDB 통합                                    │ │
│  │ • WebSocket 지원                                           │ │
│  │ • 사용량 기반 과금                                         │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  Envoy (Istio)                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ • 클라우드 네이티브                                        │ │
│  │ • 서비스 메시 사이드카                                     │ │
│  │ • gRPC 네이티브 지원                                       │ │
│  │ • 고급 트래픽 관리                                         │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  Nginx Plus / Nginx                                             │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ • 경량, 고성능                                             │ │
│  │ • 설정 기반 (코드 불필요)                                  │ │
│  │ • 광범위한 사용 사례                                       │ │
│  │ • Plus: 상용 기능 (헬스체크, 모니터링)                     │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  선택 기준:                                                     │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ • 클라우드 환경: AWS API Gateway, GCP Cloud Endpoints      │ │
│  │ • 온프레미스: Kong, Nginx                                  │ │
│  │ • Kubernetes: Envoy, Istio, NGINX Ingress                  │ │
│  │ • 간단한 요구: Nginx                                       │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4. Rate Limiting

4.1 Rate Limiting이란?

┌─────────────────────────────────────────────────────────────────┐
│                    Rate Limiting                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "단위 시간당 요청 수를 제한"                                   │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  왜 필요한가?                                              │ │
│  │                                                            │ │
│  │  • DDoS 방어                                               │ │
│  │  • 서비스 안정성 보호                                      │ │
│  │  • 공정한 리소스 분배                                      │ │
│  │  • 비용 제어                                               │ │
│  │  • API 남용 방지                                           │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  제한 기준:                                                     │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  • IP 주소별: 100 req/min per IP                           │ │
│  │  • 사용자별: 1000 req/hour per user                        │ │
│  │  • API 키별: 10000 req/day per API key                     │ │
│  │  • 엔드포인트별: /login은 5 req/min                        │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  응답 헤더:                                                     │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │  X-RateLimit-Limit: 100        # 제한                      │ │
│  │  X-RateLimit-Remaining: 45     # 남은 요청 수              │ │
│  │  X-RateLimit-Reset: 1640000000 # 리셋 시간 (Unix)          │ │
│  │                                                            │ │
│  │  제한 초과 시: 429 Too Many Requests                       │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4.2 토큰 버킷 (Token Bucket)

┌─────────────────────────────────────────────────────────────────┐
│                    토큰 버킷 알고리즘                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "버킷에 토큰이 있으면 요청 허용, 없으면 거부"                  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │           ┌──────────┐                                     │ │
│  │           │  Token   │  ◀── 일정 속도로 토큰 추가          │ │
│  │           │  Bucket  │      (예: 10개/초)                  │ │
│  │           │  ●●●●●   │                                     │ │
│  │           │  ●●●     │  ◀── 버킷 용량 (예: 100개)          │ │
│  │           └────┬─────┘                                     │ │
│  │                │                                           │ │
│  │                ▼                                           │ │
│  │  Request ──▶ 토큰 있음? ──Yes──▶ 허용 (토큰 소비)          │ │
│  │                │                                           │ │
│  │               No                                           │ │
│  │                │                                           │ │
│  │                ▼                                           │ │
│  │              거부 (429)                                    │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  특징:                                                          │
│  • 버스트 허용 (버킷에 토큰이 쌓여있으면)                       │
│  • 평균 속도 제한                                               │
│  • AWS, Stripe 등에서 사용                                      │
│                                                                  │
│  예시:                                                          │
│  버킷 크기: 100, 충전 속도: 10/초                               │
│  → 순간 100개 요청 가능 (버스트)                                │
│  → 이후 초당 10개 요청 가능                                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4.3 리키 버킷 (Leaky Bucket)

┌─────────────────────────────────────────────────────────────────┐
│                    리키 버킷 알고리즘                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "일정한 속도로만 요청 처리 (버스트 없음)"                      │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  Requests ──▶  ┌──────────┐                                │ │
│  │                │  Queue   │  ◀── 요청을 큐에 저장          │ │
│  │                │  ○○○○○   │                                │ │
│  │                │  ○○○     │  ◀── 큐 크기 제한              │ │
│  │                └────┬─────┘                                │ │
│  │                     │                                      │ │
│  │              ●      │                                      │ │
│  │              ●  ◀───┘  일정 속도로 "새어나감"              │ │
│  │              ●         (예: 10개/초)                       │ │
│  │              ▼                                             │ │
│  │           처리됨                                           │ │
│  │                                                            │ │
│  │  큐가 가득 찼을 때:                                        │ │
│  │  새 요청 ──▶ 거부 (429)                                    │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  특징:                                                          │
│  • 출력 속도가 일정 (트래픽 쉐이핑)                             │
│  • 버스트 불가                                                  │
│  • 네트워크 트래픽 조절에 적합                                  │
│                                                                  │
│  토큰 버킷 vs 리키 버킷:                                        │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │  토큰 버킷: 버스트 허용, 평균 속도 제한                    │ │
│  │  리키 버킷: 버스트 불가, 고정 속도 출력                    │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4.4 고정 윈도우 (Fixed Window)

┌─────────────────────────────────────────────────────────────────┐
│                  고정 윈도우 알고리즘                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "시간 윈도우마다 카운터 리셋"                                  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  1분 윈도우, 제한 100개:                                   │ │
│  │                                                            │ │
│  │  00:00 ~ 00:59                 01:00 ~ 01:59              │ │
│  │  ┌────────────────────┐       ┌────────────────────┐      │ │
│  │  │ Count: 0 → 100     │       │ Count: 0 (리셋)   │      │ │
│  │  │ ●●●●●●●●●●●●●●●●●  │       │ ●●●●●●●●●         │      │ │
│  │  └────────────────────┘       └────────────────────┘      │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  문제점 (경계 문제):                                            │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  00:00          00:30          01:00         01:30        │ │
│  │    │              │              │              │          │ │
│  │    └──────────────┴──────────────┴──────────────┘          │ │
│  │           │               │                                │ │
│  │           ▼               ▼                                │ │
│  │     00:30~00:59     01:00~01:29                            │ │
│  │     100개 요청      100개 요청                             │ │
│  │                                                            │ │
│  │  → 1분 사이에 200개 요청 가능!                             │ │
│  │     (00:30 ~ 01:30)                                        │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  장점: 구현 단순, 메모리 효율                                   │
│  단점: 윈도우 경계에서 버스트 가능                              │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4.5 슬라이딩 윈도우 (Sliding Window)

┌─────────────────────────────────────────────────────────────────┐
│                 슬라이딩 윈도우 알고리즘                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  "시간에 따라 윈도우가 이동 (경계 문제 해결)"                   │
│                                                                  │
│  슬라이딩 윈도우 로그:                                          │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  각 요청의 타임스탬프를 저장                               │ │
│  │  [00:30:15, 00:30:20, 00:30:45, 00:31:00, ...]             │ │
│  │                                                            │ │
│  │  현재 시간: 01:30:00                                       │ │
│  │  윈도우: 00:30:00 ~ 01:30:00 (1분)                         │ │
│  │                                                            │ │
│  │  윈도우 내 요청 수 계산                                    │ │
│  │                                                            │ │
│  │  단점: 메모리 사용량 높음 (모든 타임스탬프 저장)           │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  슬라이딩 윈도우 카운터 (최적화):                               │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                                                            │ │
│  │  이전 윈도우와 현재 윈도우의 가중 평균                     │ │
│  │                                                            │ │
│  │  현재: 01:15 (1분 윈도우)                                  │ │
│  │                                                            │ │
│  │  ├── 이전 윈도우 (00:00~01:00): 80개 ──┤                   │ │
│  │  ├── 현재 윈도우 (01:00~02:00): 40개 ──┤                   │ │
│  │                                                            │ │
│  │  01:15는 현재 윈도우의 25% 지점                            │ │
│  │  가중치: 이전 75%, 현재 25%                                │ │
│  │                                                            │ │
│  │  예상 요청 수 = 80 * 0.75 + 40 * 0.25 = 70개               │ │
│  │                                                            │ │
│  │  장점: 메모리 효율 (카운터 2개만)                          │ │
│  │        경계 문제 완화                                      │ │
│  │                                                            │ │
│  └────────────────────────────────────────────────────────────┘ │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

4.6 알고리즘 비교

알고리즘 버스트 메모리 정확도 사용 사례
토큰 버킷 허용 작음 높음 API 제한
리키 버킷 불가 작음 높음 트래픽 쉐이핑
고정 윈도우 경계 버스트 작음 낮음 단순 구현
슬라이딩 윈도우 허용 큼/중간 높음 정확한 제한

5. 연습 문제

문제 1: 리버스 프록시 설계

다음 요구사항을 만족하는 Nginx 설정을 작성하세요.

  • HTTPS 수신 (포트 443)
  • HTTP → HTTPS 리다이렉트
  • 백엔드: http://localhost:8080
  • Gzip 압축 활성화
  • 정적 파일 캐싱 (1일)

문제 2: API 게이트웨이 설계

마이크로서비스 환경에서 API 게이트웨이를 설계하세요.

서비스: - User Service: /api/users/ - Order Service: /api/orders/ - Auth Service: /api/auth/*

요구사항: - JWT 인증 (Auth 제외) - Rate Limiting: 1000 req/min per user - 응답 로깅

문제 3: Rate Limiting 선택

다음 시나리오에 적합한 Rate Limiting 알고리즘을 선택하세요.

a) 공개 API (버스트 허용, 평균 제한) b) 실시간 스트리밍 서비스 c) 로그인 엔드포인트 (브루트 포스 방지) d) 단순한 요구사항, 빠른 구현

문제 4: Rate Limiting 구현

토큰 버킷 알고리즘을 의사 코드로 구현하세요.

조건: - 버킷 크기: 100 - 충전 속도: 10 토큰/초


정답

문제 1 정답

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

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

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # Gzip 압축
    gzip on;
    gzip_types text/plain text/css application/json
               application/javascript text/xml;
    gzip_min_length 1000;

    # 정적 파일 캐싱
    location /static/ {
        expires 1d;
        add_header Cache-Control "public, immutable";
    }

    # 백엔드 프록시
    location / {
        proxy_pass http://localhost:8080;
        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;
    }
}

문제 2 정답

API Gateway 설계:

┌─────────────────────────────────────────────────┐
│                  API Gateway                    │
├─────────────────────────────────────────────────┤
│                                                 │
│  1. 요청 수신                                   │
│       │                                         │
│  2. Rate Limiting 체크 (Redis 기반)             │
│       │ key: user_id, limit: 1000/min           │
│       │                                         │
│  3. 경로 확인                                   │
│       ├── /api/auth/* → Auth Service (인증 Skip)│
│       ├── /api/users/* → JWT 검증 → User Service│
│       └── /api/orders/*→ JWT 검증 → Order Service│
│                                                 │
│  4. 응답 로깅 (ELK Stack)                       │
│       - timestamp, user_id, path, status,       │
│         response_time                           │
│                                                 │
└─────────────────────────────────────────────────┘

기술 스택:
- Kong Gateway + JWT Plugin + Rate Limiting Plugin
- 또는 AWS API Gateway + Lambda Authorizer

문제 3 정답

a) 공개 API: 토큰 버킷
   - 버스트 허용으로 사용자 경험 좋음
   - 평균 속도 제한으로 남용 방지

b) 실시간 스트리밍: 리키 버킷
   - 일정한 출력 속도로 품질 유지
   - 버스트 불가로 안정적인 전송

c) 로그인: 고정 윈도우 또는 슬라이딩 윈도우
   - 엄격한 제한 (예: 5회/분)
   - 경계 문제보다 단순함 우선

d) 단순한 요구: 고정 윈도우
   - 구현 가장 단순
   - 카운터 + 타임스탬프만 필요

문제 4 정답

class TokenBucket:
    def __init__(self, capacity=100, refill_rate=10):
        self.capacity = capacity        # 버킷 최대 크기
        self.refill_rate = refill_rate  # 초당 토큰 추가
        self.tokens = capacity          # 현재 토큰 수
        self.last_refill = current_time()

    def allow_request(self):
        self.refill()

        if self.tokens >= 1:
            self.tokens -= 1
            return True
        else:
            return False

    def refill(self):
        now = current_time()
        elapsed = now - self.last_refill

        # 경과 시간에 비례하여 토큰 추가
        tokens_to_add = elapsed * self.refill_rate
        self.tokens = min(self.capacity, self.tokens + tokens_to_add)
        self.last_refill = now

# 사용 예
bucket = TokenBucket(capacity=100, refill_rate=10)

if bucket.allow_request():
    process_request()
else:
    return 429  # Too Many Requests

6. 다음 단계

리버스 프록시와 API 게이트웨이를 이해했다면, 캐싱 전략을 학습하세요.

다음 레슨

관련 레슨

추천 실습

  1. Nginx 리버스 프록시 설정 실습
  2. Kong Gateway 설치 및 플러그인 테스트
  3. Rate Limiting 직접 구현해보기

7. 참고 자료

도구

문서

알고리즘


문서 정보 - 최종 수정: 2024년 - 난이도: ⭐⭐⭐ - 예상 학습 시간: 2-3시간

to navigate between lessons