🌍 네트워크

Proxy

프록시

클라이언트-서버 사이 중개자. 캐싱, 보안, 로드밸런싱.

Forward vs Reverse Proxy

프록시는 위치와 역할에 따라 크게 두 가지로 구분됩니다. Forward Proxy는 클라이언트 측에서 외부 인터넷 접근을 대리하고, Reverse Proxy는 서버 측에서 내부 서버를 보호하고 트래픽을 분산합니다.

Forward Proxy
클라이언트 측 프록시

클라이언트가 외부 서버에 접근할 때 요청을 대신 전달합니다. 클라이언트의 IP를 숨기고, 접근 제어 및 콘텐츠 필터링을 수행합니다.

기업 네트워크 인터넷 접근 제어
사용자 익명성 보장 (IP 숨김)
지역 제한 콘텐츠 우회
악성 사이트 접근 차단
대표 도구
Squid Privoxy CCProxy
Reverse Proxy
서버 측 프록시

외부 요청을 받아 내부 서버로 전달합니다. 서버의 실제 IP를 숨기고, 로드 밸런싱, SSL 종료, 캐싱 등을 처리합니다.

로드 밸런싱 (트래픽 분산)
SSL/TLS 종료 (인증서 관리)
정적 콘텐츠 캐싱
DDoS 공격 방어
대표 도구
Nginx HAProxy Traefik
💻
Client
🛡
Forward Proxy
🌐
Internet
클라이언트 IP 숨김 | 접근 제어 | 콘텐츠 필터링
🌐
Internet
🛡
Reverse Proxy
🖥
Backend Servers
SSL 종료 | 로드 밸런싱 | 캐싱 | 보안
💻
User
CDN Edge
🛡
Nginx
🖥
Origin
Cloudflare/Akamai (Edge) + Nginx (Origin) 이중 캐싱 구조

📦 프록시 캐싱 메커니즘

프록시 캐싱은 자주 요청되는 콘텐츠를 프록시 서버에 저장하여 원본 서버 부하를 줄이고 응답 속도를 개선합니다. 적절한 캐싱 전략은 서버 비용을 70-90% 절감할 수 있습니다.

📋 Cache-Control 헤더

max-age, no-cache, no-store, private, public 등의 지시어로 캐싱 동작을 세밀하게 제어합니다.

🔧 ETag/Last-Modified

조건부 요청(If-None-Match, If-Modified-Since)으로 변경 여부만 확인하여 304 응답으로 대역폭을 절약합니다.

🔢 Cache Key

URL, 쿼리 파라미터, 헤더(Accept-Language, Accept-Encoding)를 조합하여 캐시를 구분합니다.

🔄 Cache Invalidation

PURGE 요청, TTL 만료, 태그 기반 무효화로 오래된 캐시를 제거합니다. "컴퓨터 과학에서 가장 어려운 문제 중 하나"입니다.

<10ms
Cache Hit 응답 시간
80-95%
일반적인 Hit Rate
70-90%
서버 부하 절감

🔒 프록시 보안 기능

프록시는 네트워크 보안의 핵심 컴포넌트입니다. 클라이언트와 서버 사이에 위치하여 악성 트래픽을 필터링하고, 민감한 정보를 보호하며, 공격을 탐지/차단합니다.

🔒
SSL/TLS 종료
프록시에서 HTTPS 복호화하여 백엔드 서버 부담 감소. 인증서 관리 일원화.
🛡
WAF (Web Application Firewall)
SQL Injection, XSS, CSRF 등 OWASP Top 10 공격 탐지 및 차단.
🌟
Rate Limiting
IP/사용자별 요청 횟수 제한으로 무차별 공격 및 API 남용 방지.
🚫
DDoS 방어
대규모 트래픽 흡수, 봇 탐지, CAPTCHA 챌린지로 서비스 가용성 보장.
👁
IP Masking
실제 서버 IP를 숨겨 직접 공격 방지. Origin Shield 역할.
📝
로깅 & 모니터링
모든 트래픽 로그 수집, 이상 징후 탐지, 보안 감사 지원.

🛠 도구 비교: Nginx vs Squid vs HAProxy

프록시 도구는 용도에 따라 선택이 달라집니다. 웹 서버/리버스 프록시는 Nginx, Forward Proxy/캐싱은 Squid, 고성능 로드 밸런싱은 HAProxy가 대표적입니다.

도구 주요 용도 Reverse Proxy Forward Proxy 캐싱 특징
Nginx 인기 웹 서버, 리버스 프록시 탁월 제한적 우수 경량, 높은 동시성, 설정 간단
Squid Forward Proxy, 캐싱 가능 탁월 탁월 강력한 ACL, 대용량 캐시
HAProxy 엔터프라이즈 로드 밸런싱, TCP 프록시 탁월 미지원 미지원 초고성능, L4/L7 지원, 헬스체크
Traefik 클라우드 네이티브 프록시 탁월 미지원 제한적 자동 설정, Docker/K8s 통합
Envoy 서비스 메시, API Gateway 탁월 미지원 가능 gRPC 지원, Observability

📈 프록시 트래픽 시뮬레이션

프록시가 요청을 처리하는 과정을 실시간으로 확인해보세요. 캐시 히트, 캐시 미스, 차단된 요청의 흐름을 시각적으로 이해할 수 있습니다.

[00:00:00] → GET /api/users CACHE MISS - 원본 서버 요청 (245ms)
[00:00:01] → GET /api/users CACHE HIT - 캐시 응답 (3ms)
[00:00:02] → GET /static/logo.png CACHE HIT - 캐시 응답 (1ms)
[00:00:03] → POST /api/login - 프록시 통과 (89ms)
[00:00:04] → GET /admin/config BLOCKED - 접근 거부 (IP 차단)

📖 상세 설명

프록시(Proxy)는 '대리인'이라는 뜻으로, 네트워크에서 클라이언트와 서버 사이에 위치하여 요청과 응답을 중계하는 서버입니다. 클라이언트가 직접 서버에 접속하는 대신, 프록시 서버가 대신 요청을 전달하고 응답을 받아 클라이언트에게 전달합니다. 이를 통해 캐싱, 보안, 익명성, 로드 밸런싱 등 다양한 이점을 얻을 수 있습니다.

프록시는 크게 Forward Proxy와 Reverse Proxy로 구분됩니다. Forward Proxy는 클라이언트 측에 위치하여 클라이언트의 요청을 대신 전달하며, 기업 네트워크에서 인터넷 접근 제어나 사용자의 IP 주소 숨기기에 사용됩니다. 대표적으로 Squid, Privoxy 등이 있습니다. Reverse Proxy는 서버 측에 위치하여 외부 요청을 내부 서버로 분배하며, Nginx, HAProxy가 대표적입니다.

프록시의 캐싱 기능은 네트워크 트래픽을 크게 줄여줍니다. 자주 요청되는 콘텐츠를 프록시 서버에 저장해두면, 원본 서버까지 요청을 보내지 않고도 빠르게 응답할 수 있습니다. CDN(Content Delivery Network)도 일종의 분산된 캐싱 프록시로 볼 수 있으며, 전 세계에 배치된 엣지 서버에서 콘텐츠를 캐싱하여 사용자에게 가장 가까운 위치에서 서비스합니다.

보안 측면에서 프록시는 방화벽, SSL/TLS 종료, DDoS 방어, 악성 트래픽 필터링 등 다양한 역할을 수행합니다. 현대 웹 아키텍처에서 Nginx나 Envoy 같은 리버스 프록시는 API Gateway 역할을 하며, 인증, 속도 제한(Rate Limiting), 로깅, 모니터링 등 횡단 관심사(Cross-cutting Concerns)를 처리합니다. Kubernetes 환경에서는 Ingress Controller가 이 역할을 담당합니다.

💻 코드 예제

# Nginx Reverse Proxy 설정 (/etc/nginx/nginx.conf)

# 기본 리버스 프록시 설정
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend-server: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;
    }
}

# 로드 밸런싱 설정
upstream backend {
    least_conn;  # 최소 연결 알고리즘
    server backend1:8080 weight=3;
    server backend2:8080 weight=2;
    server backend3:8080 backup;  # 백업 서버
}

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

    ssl_certificate /etc/ssl/certs/example.crt;
    ssl_certificate_key /etc/ssl/private/example.key;

    # 캐싱 설정
    proxy_cache_path /var/cache/nginx levels=1:2
                     keys_zone=my_cache:10m max_size=1g;

    location /api/ {
        proxy_pass http://backend;
        proxy_cache my_cache;
        proxy_cache_valid 200 10m;
        proxy_cache_valid 404 1m;

        # 타임아웃 설정
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
    }
}
import requests
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request

# 프록시를 통한 HTTP 요청 (requests 라이브러리)
proxies = {
    'http': 'http://proxy.example.com:8080',
    'https': 'http://proxy.example.com:8080',
}

# 프록시를 통해 요청 보내기
response = requests.get('https://api.example.com/data',
                        proxies=proxies,
                        timeout=30)
print(response.json())

# SOCKS 프록시 사용 (pip install requests[socks])
socks_proxies = {
    'http': 'socks5://localhost:9050',   # Tor
    'https': 'socks5://localhost:9050',
}
response = requests.get('https://check.torproject.org',
                        proxies=socks_proxies)


# 간단한 HTTP 프록시 서버 구현
class ProxyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # 요청 URL로 프록시 요청
        try:
            with urllib.request.urlopen(self.path) as response:
                self.send_response(response.status)
                for header, value in response.getheaders():
                    self.send_header(header, value)
                self.end_headers()
                self.wfile.write(response.read())
        except Exception as e:
            self.send_error(500, str(e))

# 프록시 서버 실행 (포트 8888)
# server = HTTPServer(('localhost', 8888), ProxyHandler)
# server.serve_forever()

# 환경 변수로 프록시 설정
import os
os.environ['HTTP_PROXY'] = 'http://proxy.example.com:8080'
os.environ['HTTPS_PROXY'] = 'http://proxy.example.com:8080'
os.environ['NO_PROXY'] = 'localhost,127.0.0.1,.internal.com'
# Squid Forward Proxy 설정 (/etc/squid/squid.conf)

# 기본 포트 설정
http_port 3128

# 접근 제어 리스트 (ACL)
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16

acl SSL_ports port 443
acl Safe_ports port 80 443 8080

# 접근 허용/거부 규칙
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access deny all

# 캐싱 설정 (1GB 캐시)
cache_dir ufs /var/spool/squid 1000 16 256
maximum_object_size 100 MB
cache_mem 256 MB

# 익명성 설정 (클라이언트 IP 숨기기)
forwarded_for off
request_header_access Via deny all
request_header_access X-Forwarded-For deny all

# 차단할 도메인
acl blocked_sites dstdomain .facebook.com .youtube.com
http_access deny blocked_sites

# -------------------------------------------
# curl에서 프록시 사용
curl -x http://proxy.example.com:8080 https://api.example.com
curl --proxy socks5://localhost:9050 https://check.torproject.org

# 환경 변수로 프록시 설정 (Linux/macOS)
export http_proxy="http://proxy.example.com:8080"
export https_proxy="http://proxy.example.com:8080"
export no_proxy="localhost,127.0.0.1,.internal.com"

# Git에서 프록시 설정
git config --global http.proxy http://proxy.example.com:8080
git config --global https.proxy http://proxy.example.com:8080

# npm에서 프록시 설정
npm config set proxy http://proxy.example.com:8080
npm config set https-proxy http://proxy.example.com:8080

🗣️ 실무에서 이렇게 말하세요

💬 아키텍처 설계 회의에서
"API 서버 앞에 Nginx를 리버스 프록시로 두면 SSL 종료, 로드 밸런싱, 정적 파일 캐싱을 한 번에 처리할 수 있습니다. 백엔드 서버는 HTTP만 처리하면 되니까 성능도 올라가고, 인증서 관리도 Nginx 한 곳에서만 하면 됩니다."
💬 보안 검토 회의에서
"Forward Proxy를 도입해서 아웃바운드 트래픽을 제어하는 게 좋겠습니다. 내부 서버가 외부와 통신할 때 반드시 프록시를 거치게 하면, 악성 도메인 접근 차단과 데이터 유출 모니터링이 가능합니다. Squid로 화이트리스트 방식으로 운영하면 됩니다."
💬 성능 최적화 논의에서
"API 응답 시간이 느린 건 프록시 캐싱으로 해결할 수 있습니다. 변경이 적은 GET 요청은 Nginx에서 proxy_cache로 10분 정도 캐싱하면 백엔드 부하를 80% 이상 줄일 수 있어요. Cache-Control 헤더도 같이 설정해서 CDN 캐싱도 활용하면 좋겠습니다."

⚠️ 흔한 실수 & 주의사항

X-Forwarded-For 헤더 신뢰

클라이언트가 X-Forwarded-For 헤더를 조작할 수 있습니다. 프록시 체인에서 마지막 신뢰할 수 있는 프록시가 추가한 값만 사용하세요. Nginx의 realip_module로 신뢰할 IP 대역을 명시적으로 설정해야 합니다.

WebSocket/SSE 프록시 설정 누락

일반 HTTP 프록시 설정만으로는 WebSocket이 작동하지 않습니다. Nginx에서 Upgrade, Connection 헤더를 명시적으로 전달해야 하며, 타임아웃 설정도 길게 조정해야 연결이 끊기지 않습니다.

캐싱으로 인한 민감 데이터 노출

사용자별 개인 데이터가 포함된 응답을 캐싱하면 다른 사용자에게 노출될 수 있습니다. Cache-Control: private, no-store 헤더를 확인하고, 인증이 필요한 엔드포인트는 캐싱에서 제외하세요.

올바른 프록시 설정 방법

프록시 헤더(X-Real-IP, X-Forwarded-For, X-Forwarded-Proto) 설정, 적절한 타임아웃 값, 헬스체크 설정, 버퍼 크기 조정을 반드시 확인하세요. proxy_next_upstream으로 장애 시 자동 failover도 설정하세요.

🔗 관련 용어

📚 더 배우기