Web Server - Proxy와 Reverse Proxy
Proxy(프록시)와 Reverse Proxy(리버스 프록시)는 Client-Server model에서 익명성(Anonymity)과 성능/보안(Performance/Security)을 제공하는 핵심 기술입니다.
직관적 이해
- 클라이언트 보호 중심: Proxy = 비서(Secretary)
- 서버 보호 중심: Reverse Proxy = 리셉션(Front Desk)
요약
| 구분 | 익명성 (Anonymity) | 성능/보안 (Performance & Security) |
|---|---|---|
| Proxy (Forward Proxy) | - 클라이언트 IP 숨김- 웹 필터링(접속 기록 은폐) - 클라이언트 접근 제한 지역 우회 | - 캐싱(Cache)으로 응답 속도 향상 - 기업 방화벽에서 트래픽 모니터링 |
| Reverse Proxy | - 서버의 실제 IP/구조 은폐 - 클라이언트는 단일 리셉션만 인식 | - 로드 밸런싱(Load Balancing) - SSL 종료(TLS Termination) - DDoS 완화 및 WAF(Web Application Firewall) |
Proxy와 Reverse Proxy는 겉으로 보기엔 단순히 트래픽을 ‘우회’시키는 것 같지만 목적이 다릅니다.
- Proxy는 사용자(클라이언트)의 익명성 확보와 제어가 핵심이며,
- Reverse Proxy는 서버의 보안 강화와 성능 최적화에 중점을 둡니다.
Webhook (웹훅)
- 정의: 으로, Sender (발신 서버 A)가 특정 이벤트 발생 시 다른 Receiver(수신 서버 B)에 HTTP 에 따른 요청(주로 POST)을 보내 알림 또는 데이터를 전달하는 “Event (trigger) 기반 서버 간 통신 방식”. 이때 주고받는 데이터는 주로 JSON(JavaScript Object Notation) 포맷을 사용합니다.
- 동작 방식:
- Sender-Receiver 구조:
- Webhook 방식 vs Polling with APIs 방식
| 구분 | Webhook (웹훅) | Polling with APIs |
|---|---|---|
| 방식 | A 서버가 이벤트 발생 시 자동으로 B 서버에 전송 | B 서버가 일정 주기로 A 서버에 이벤트가 있는지 직접 요청 |
| 효율성 | 이벤트가 있을 때만 전송, 효율적 | 불필요한 요청이 많아 서버 리소스 낭비 |
| 실시간성 | 실시간 알림 가능 | 실시간이 아님 |
예시: Webhook 통신 흐름
- Sender (A 서버)에서 이벤트 발생 (예: 사용자가 상품을 결제).
- Sender가 Receiver (B 서버)의 Webhook URL(예:
https://a-server.com/webhook)로 HTTP POST 요청을 전송. - Receiver는 POST Body의 JSON 데이터를 파싱하여 처리(DB 저장, 알림 발송 등).
- Receiver는 성공 여부를 HTTP 응답 코드(예:
200 OK)로 반환.
Sender(A 서버)가 B 서버로 보내는 데이터 (JSON 파일 형식):
json
{
"event": "payment_completed",
"timestamp": "2025-07-26T09:23:15Z",
"data": {
"payment_id": "pay_123456789",
"user": {
"id": "user_98765",
"email": "user@example.com",
"name": "Alice Kim"
},
"amount": 49900,
"currency": "KRW",
"status": "success"
},
"signature": "f3b9a8d8a4e... (HMAC-SHA256)"
}event: 어떤 이벤트가 발생했는지 명시 (예:payment_completed).timestamp: 이벤트가 발생한 시간 (ISO 8601 형식).data: 이벤트와 관련된 상세 데이터.signature: 보안 검증용 HMAC 서명 값. Sender가 Webhook Payload를 해싱(HMAC-SHA256)하여 A 서버가 데이터 위변조 여부를 검증할 수 있도록 전달.
Receiver (B 서버)의 Webhook 엔드포인트 (Python Flask 예시):
python
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
SECRET_KEY = b'shared_secret_key'
@app.route('/webhook', methods=['POST'])
def webhook_receiver():
# 요청 데이터(JSON) 파싱
payload = request.get_data()
received_signature = request.json.get('signature')
# HMAC-SHA256 서명 검증
expected_signature = hmac.new(SECRET_KEY, payload, hashlib.sha256).hexdigest()
if received_signature != expected_signature:
return jsonify({"message": "Invalid signature"}), 403
# 실제 이벤트 데이터 처리
event = request.json.get('event')
data = request.json.get('data')
print(f"Webhook event: {event}, data: {data}")
return jsonify({"message": "Webhook received"}), 200
if __name__ == '__main__':
app.run(port=5000)JSON vs curl의 차이
| 구분 | JSON 포맷 | curl 포맷 |
|---|---|---|
| 목적 | Webhook 요청 Body 내용만 설명 | 실제 HTTP 요청(헤더 + Body)을 커맨드라인에서 실행 가능 |
| 구성 | 순수 데이터 구조 (Key-Value) | HTTP 메서드(-X), 헤더(-H), 데이터(-d) 등을 명시 |
| 용도 | Sender가 보내는 Payload의 내부 구조 확인 | Receiver에 직접 테스트 요청 전송 시 활용 |
Webhook 요청(JSON 예시)
Sender(A 서버)가 B 서버의 엔드포인트(https://a-server.com/webhook)로 HTTP POST 요청을 보낼 때, Body(본문*를 JSON 형식으로 보냅니다.
json
{
"event": "payment_completed",
"timestamp": "2025-07-26T09:23:15Z",
"data": {
"payment_id": "pay_123456789",
"user": {
"id": "user_98765",
"email": "user@example.com",
"name": "Alice Kim"
},
"amount": 49900,
"currency": "KRW",
"status": "success"
},
"signature": "f3b9a8d8a4e... (HMAC-SHA256)"
}
동일 요청을 curl로 표현
Webhook은 단순히 HTTP 요청이므로, curl 명령어로 쉽게 시뮬레이션할 수 있습니다.
shell
curl -X POST "https://a-server.com/webhook" \
-H "Content-Type: application/json" \
-H "X-Signature: f3b9a8d8a4e... (HMAC-SHA256)" \
-d '{
"event": "payment_completed",
"timestamp": "2025-07-26T09:23:15Z",
"data": {
"payment_id": "pay_123456789",
"user": {
"id": "user_98765",
"email": "user@example.com",
"name": "Alice Kim"
},
"amount": 49900,
"currency": "KRW",
"status": "success"
}
}'