리버스 프록시란 무엇인가: 개념부터 SSL 터미네이션·헤더 조작까지 한 번에 잡는 원리 가이드

브라우저가 naver.com에 요청을 보낼 때, 실제로 TCP 연결을 받고 응답을 돌려주는 서버가 naver.com 오리진 서버가 아닐 수 있습니다. 수십 개의 오리진 서버 앞에 조용히 앉아 있는 리버스 프록시가 요청을 받고, SSL을 해제하고, 헤더를 덧붙이고, 가장 한가한 백엔드로 넘겨줍니다. 클라이언트는 이 중간 행위자의 존재를 전혀 알지 못합니다. 저희가 DevOps 실무에서 Nginx와 HAProxy를 다루다 보면, 리버스 프록시가 단순한 포워딩 장치가 아니라 트래픽 처리의 핵심 결정 지점이라는 사실을 매번 재확인하게 됩니다. OSI 모델, SSL 터미네이션, 헤더 조작, 보안 아키텍처 순서로 리버스 프록시의 무엇, 왜, 어떻게를 한 번에 짚겠습니다. 구체적인 Nginx·HAProxy 설정은 Nginx·HAProxy로 구축하는 리버스 프록시 실전 설정 가이드(2부)에서 이어집니다.
프록시의 두 얼굴 — 포워드 프록시 vs. 리버스 프록시의 결정적 차이
"프록시"라는 단어는 두 개의 완전히 다른 장치를 가리킵니다. 같은 이름을 쓰지만 트래픽 흐름이 정반대이고, 설정 주체도 다릅니다.
**포워드 프록시(Forward Proxy)**는 클라이언트 측 대리인입니다. 기업 내부망에서 외부 인터넷으로 나가는 요청을 대신 처리합니다. 클라이언트(브라우저, 앱)가 "이 서버를 내 프록시로 써라"고 직접 설정합니다. 기업 방화벽, VPN 게이트웨이, 학교 인터넷 필터링이 이 방식으로 동작합니다. 외부 서버 입장에서는 클라이언트의 실제 IP 대신 프록시 IP를 보게 됩니다.
**리버스 프록시(Reverse Proxy)**는 서버 측 대리인입니다. 클라이언트가 직접 접근한다고 믿는 서버 앞에 투명하게 위치합니다. 클라이언트는 리버스 프록시의 존재를 전혀 모릅니다. Nginx가 example.com 앞에 서서 포트 443을 받고, 내부의 포트 8080 앱 서버로 넘겨주는 것이 전형적인 예입니다. Cloudflare가 수백만 개 사이트의 트래픽을 앞에서 받는 것도 같은 원리입니다.
RFC 9110 Section 3.7 "Intermediaries"는 HTTP 중간 행위자를 Proxy, Gateway, Tunnel, 세 가지로 규정합니다. RFC 9110의 용어 정의에 따르면 **Gateway(게이트웨이)**가 바로 리버스 프록시에 해당하는 공식 명칭입니다: "게이트웨이는 아웃바운드 연결에서 오리진 서버처럼 행동하지만, 수신한 요청을 다른 서버로 인바운드 포워딩한다." 반면 일반적인 포워드 프록시는 RFC에서 Proxy로 부릅니다.
두 프록시의 트래픽 흐름을 비교하면 다음과 같습니다.
=== 포워드 프록시 ===
[클라이언트] ──설정됨──▶ [포워드 프록시] ──▶ [외부 서버]
(IP: 10.0.0.5) (IP: 203.0.113.1) (IP: 외부)
클라이언트가 직접 설정 클라이언트 신원 숨김
=== 리버스 프록시 ===
[클라이언트] ──────────▶ [리버스 프록시] ──▶ [오리진 서버]
(IP: 외부) (IP: 203.0.113.2) (IP: 10.0.1.x)
존재를 모름 서버 신원 숨김
example.com이라고 믿음
포워드 프록시는 클라이언트를 대신해서 외부 세계와 소통하고, 리버스 프록시는 서버를 대신해서 외부 클라이언트와 소통합니다. 이 방향성 하나가 두 장치의 설정 방식, 보안 모델, 책임 범위를 완전히 가릅니다.
OSI 모델 어디에 사는가 — L4 프록시와 L7 프록시의 처리 방식 비교
리버스 프록시를 도입할 때 반드시 결정해야 하는 것이 있습니다. "어느 OSI 계층에서 동작하는 프록시를 쓸 것인가"입니다. L4와 L7은 처리할 수 있는 정보의 범위가 근본적으로 다르고, 그 차이는 구현 가능한 기능 목록을 결정합니다.
L4 프록시는 TCP(Transmission Control Protocol, 전송 제어 프로토콜)/UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜) 패킷 레벨에서 동작합니다. 패킷의 IP 주소와 포트 번호만 봅니다. HTTP 헤더나 URL은 해석하지 않고, 바이트 스트림을 그대로 백엔드로 릴레이합니다. HAProxy TCP 모드, AWS NLB(Network Load Balancer)가 대표적입니다. 지연 시간이 낮고 처리량이 높은 것이 장점이지만, 요청 내용을 볼 수 없으므로 URL 기반 라우팅, 쿠키 기반 어피니티, HTTP 헤더 조작은 불가능합니다.
L7 프록시는 애플리케이션 레이어까지 올라와 HTTP 헤더, URL 경로, 쿠키, 요청 본문을 파싱합니다. 요청 내용을 보고 결정을 내릴 수 있기 때문에 /api/v1/* 경로는 API 서버로, /static/* 경로는 CDN 오리진으로 분리 라우팅하는 것이 가능합니다. Nginx HTTP 모드, Envoy, Traefik이 여기에 속합니다.
| 항목 | L4 프록시 | L7 프록시 |
|---|---|---|
| 처리 계층 | Transport (TCP/UDP) | Application (HTTP/gRPC) |
| 라우팅 기준 | IP 주소 + 포트 | URL, 헤더, 쿠키, 메서드 |
| TLS 처리 위치 | 백엔드 서버 또는 Passthrough | 프록시 레벨에서 터미네이션 가능 |
| 헤더 조작 | 불가 | 자유롭게 추가/수정/삭제 |
| 쿠키 기반 세션 어피니티 | 불가 | 가능 (sticky session) |
| 처리 속도 오버헤드 | 낮음 | HTTP 파싱 비용 존재 |
| 대표 소프트웨어 | HAProxy TCP 모드, AWS NLB | Nginx, Envoy 1.38, HAProxy HTTP 모드 |
L7 프록시가 CPU와 메모리를 더 소비하는 것은 사실입니다. 그럼에도 저희 팀이 운영하는 MSA(Microservices Architecture, 마이크로서비스 아키텍처) 환경에서는 L7을 기본으로 선택합니다. URL 경로 기반의 서비스 분리, 헤더를 통한 요청 추적, 쿠키 어피니티로 구현하는 스테이트풀 세션 — 이 세 가지 이점만으로 L7 파싱 오버헤드를 충분히 정당화할 수 있기 때문입니다. 데이터베이스 쿼리 성능 최적화 사례가 궁금하다면 데이터베이스 인덱싱의 원리와 최적화에서 유사한 레이어별 분석을 확인할 수 있습니다.
리버스 프록시가 실제로 하는 일 6가지 — 단순 포워딩이 아니다
리버스 프록시를 "단순히 요청을 통과시키는 파이프"로 이해하면 기능의 절반을 놓칩니다. 실제 운영 환경에서 리버스 프록시는 아래 여섯 가지 역할을 동시에 수행합니다.
1. SSL/TLS 터미네이션
클라이언트가 HTTPS로 연결하면, 리버스 프록시가 TLS(Transport Layer Security, 전송 계층 보안) 핸드셰이크를 직접 처리합니다. 핸드셰이크가 끝난 뒤 내부 백엔드로는 평문 HTTP를 전달합니다. 인증서 관리를 오리진 서버 각각이 아닌 프록시 한 곳에서 일원화할 수 있습니다. Let's Encrypt 자동 갱신도 프록시 레벨에서만 설정하면 됩니다.
2. 로드밸런싱(Load Balancing)
여러 백엔드 서버로 요청을 분산합니다. 알고리즘은 목적에 따라 고릅니다. Round Robin은 순서대로 균등 배분하고, Least Connection은 현재 연결 수가 가장 적은 서버를 선택하므로 처리 시간 편차가 큰 요청(예: 영상 변환 API)에 잘 맞습니다. IP Hash는 클라이언트 IP를 해시해 항상 동일한 백엔드로 보내기 때문에, 세션 상태를 서버 메모리에 저장하는 레거시 앱에서 주로 씁니다.
3. 응답 캐싱(Response Caching)
백엔드가 돌려준 응답을 프록시가 캐시에 저장합니다. 동일 요청이 다시 오면 오리진까지 가지 않고 캐시에서 즉시 응답합니다. Cache-Control: max-age=3600 헤더가 있으면 그 TTL(Time to Live, 유효 시간)을 준수하고, ETag 기반 조건부 요청으로 변경 여부를 먼저 확인합니다.
4. 요청·응답 헤더 조작
클라이언트 IP를 X-Forwarded-For 헤더에 담아 백엔드에 전달하거나, 불필요한 응답 헤더를 제거하거나, CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유) 헤더를 프록시 레벨에서 일괄 추가할 수 있습니다. 상세 내용은 아래 헤더 조작 섹션에서 깊게 다룹니다.
5. 압축(Compression)
백엔드가 압축 처리를 하지 않더라도, 프록시가 응답 본문을 Gzip 또는 Brotli로 압축해 클라이언트에게 전달합니다. Accept-Encoding 헤더를 확인해 클라이언트가 지원하는 형식으로 선택 압축합니다. Brotli는 Gzip 대비 텍스트 기반 리소스에서 20~26% 더 작은 크기를 만들어냅니다.
6. 속도 제한(Rate Limiting)
IP별, 또는 인증 토큰별로 초당 허용 요청 수를 제한합니다. 비정상적으로 높은 빈도로 요청하는 클라이언트를 프록시 레벨에서 조기 차단해 백엔드 서버의 부하를 보호합니다. 429 Too Many Requests 응답을 돌려주고, Retry-After 헤더로 재시도 시점을 안내합니다.
이 여섯 가지를 모두 오리진 서버에서 직접 구현하면 서비스 코드가 인프라 관심사로 오염됩니다. 리버스 프록시는 이 책임을 서비스 코드 바깥으로 꺼내는 역할을 합니다.
SSL 터미네이션 깊게 파헤치기 — TLS 핸드셰이크가 어디서 끝나는가
SSL 터미네이션(SSL Termination)은 리버스 프록시의 역할 중 가장 오해가 많은 부분입니다. "SSL을 끊는다"는 표현이 마치 보안을 해제하는 것처럼 들리지만, 실제로는 어디서 TLS를 처리하느냐의 문제입니다.
TLS 핸드셰이크의 흐름을 요약하면 다음과 같습니다. 클라이언트가 ClientHello를 보내 지원 암호화 스위트(Cipher Suite)와 TLS 버전을 알립니다. 서버가 ServerHello로 사용할 암호화 스위트를 선택하고 인증서를 전달합니다. 클라이언트가 인증서를 검증하고 세션 키를 협상합니다. ChangeCipherSpec과 Finished 메시지 교환으로 암호화 통신이 시작됩니다. 이 과정이 리버스 프록시에서 일어나면, 오리진 서버는 TLS 오버헤드를 전혀 지지 않습니다.
리버스 프록시 환경에서 SSL 처리 방식은 세 가지 패턴으로 나뉩니다.
=== 패턴 1: Edge Termination (엣지 터미네이션) ===
[클라이언트] ──HTTPS──▶ [리버스 프록시] ──HTTP──▶ [백엔드]
TLS 종료↑ 평문 전달
=== 패턴 2: Re-encryption (재암호화) ===
[클라이언트] ──HTTPS──▶ [리버스 프록시] ──HTTPS──▶ [백엔드]
TLS 종료↑ 재암호화↑ 내부 인증서
=== 패턴 3: TLS Passthrough (패스스루) ===
[클라이언트] ──HTTPS──▶ [리버스 프록시] ──HTTPS──▶ [백엔드]
SNI만 확인 패킷 그대로 통과 TLS 종료
각 패턴에는 명확한 트레이드오프가 있습니다.
Edge Termination은 가장 흔한 설정입니다. 프록시가 TLS 처리를 전담하므로 백엔드 서버의 CPU 부하가 줄고 인증서 관리가 단순합니다. 단점은 프록시와 백엔드 사이 구간이 평문 HTTP입니다. 두 서버가 같은 데이터센터 내부 네트워크에 있다면 대부분 허용 가능한 수준이지만, 규정 준수(컴플라이언스) 요구사항이 있는 환경(금융, 의료)에서는 추가 검토가 필요합니다.
Re-encryption은 프록시에서 한 번 복호화한 뒤 백엔드로 보낼 때 다시 암호화합니다. 내부망 구간도 암호화가 유지되므로 컴플라이언스 요건을 만족합니다. 대신 프록시가 두 번의 TLS 처리를 하므로 CPU 비용이 증가하고, 백엔드용 내부 인증서 관리가 추가됩니다.
TLS Passthrough는 프록시가 TLS를 전혀 보지 않습니다. SNI(Server Name Indication, 서버 이름 표시) 헤더만 확인해 어느 백엔드로 라우팅할지 결정하고, TLS 패킷을 그대로 통과시킵니다. 프록시가 암호화된 내용을 볼 수 없으므로 헤더 조작, 캐싱, 요청 로깅이 불가능합니다. 종단간 암호화가 강하게 요구되고 프록시 레벨 기능이 필요 없을 때 선택합니다.
저희가 실제 프로젝트에서 선택한 기준은 단순합니다. 내부망 보안 요건이 없으면 Edge Termination을, 내부 구간 암호화가 강하게 요구되는 환경에서는 Re-encryption을, 데이터베이스 TLS 터널처럼 HTTP 계층 개입 없이 TCP 라우팅만 필요하면 Passthrough를 우선 후보로 둡니다. 다만 실제 도입 시에는 각 조직이 따라야 하는 컴플라이언스 문서와 보안 정책을 별도로 검토해야 합니다.
헤더 조작의 원리와 함정 — X-Forwarded-For를 잘못 믿으면 생기는 일
리버스 프록시가 도입되면 백엔드 애플리케이션은 클라이언트의 실제 IP를 직접 볼 수 없습니다. 요청을 보내는 주체가 클라이언트가 아닌 프록시 서버가 되기 때문입니다. 이를 해결하기 위해 프록시는 클라이언트 IP를 X-Forwarded-For 헤더에 담아 백엔드로 전달합니다.
문제는 이 헤더가 연쇄 프록시 환경에서 쌓이는 방식에서 시작됩니다. 클라이언트 IP가 192.0.2.1이고, 두 개의 프록시(ProxyA → ProxyB)를 거쳐 백엔드에 도달하는 경우를 생각해봅니다. ProxyA는 X-Forwarded-For: 192.0.2.1를 붙입니다. ProxyB는 이미 있는 값에 append해 X-Forwarded-For: 192.0.2.1, 10.0.0.1을 만듭니다. 백엔드에서 이 헤더를 받으면 왼쪽부터 순서대로 클라이언트, ProxyA, ProxyB의 IP가 쌓여 있습니다. 가장 오른쪽 값이 마지막으로 추가한 신뢰할 수 있는 프록시의 IP입니다.
그런데 여기서 함정이 있습니다. 악의적인 클라이언트가 요청에 X-Forwarded-For: 192.0.2.1를 직접 주입할 수 있습니다. 신뢰하는 프록시가 그 값을 append하면 X-Forwarded-For: 192.0.2.1, 실제클라이언트IP가 됩니다. 백엔드가 맹목적으로 첫 번째 값을 클라이언트 IP로 믿으면 192.0.2.1로 속게 됩니다. 이 문제를 **헤더 주입(Header Injection)**이라고 부릅니다.
신뢰할 수 있는 IP를 추출하는 올바른 방법은 "오른쪽에서 N번째 값"을 사용하는 것입니다. N은 내가 운영하는 신뢰 프록시의 개수입니다. 프록시가 하나라면 오른쪽에서 첫 번째 값(마지막 값)이 실제 클라이언트 IP가 됩니다.
RFC 9110은 X-Forwarded-For를 공식 표준으로 채택하지 않았습니다. 대신 RFC 9110 기반의 표준 헤더는 Forwarded 입니다. Forwarded: for=192.0.2.1;proto=https;by=10.0.0.1 형식으로 구조화된 정보를 담습니다. X-Forwarded-For, X-Real-IP, X-Forwarded-Proto는 오랜 관습이지만 표준이 아닙니다. 새로 설계하는 인프라라면 표준 Forwarded 헤더를 우선적으로 고려하는 것을 권장합니다.
Express.js에서 IP 추출을 올바르게 처리하는 코드는 다음과 같습니다.
const express = require('express');
const app = express();
// 신뢰하는 프록시가 1개(Nginx 1대)인 경우
// 'trust proxy'를 1로 설정하면 Express가 X-Forwarded-For에서
// 오른쪽 끝 1개 항목(프록시 IP)을 제거하고, 남은 가장 왼쪽 값을
// 클라이언트 IP(req.ip)로 반환한다.
app.set('trust proxy', 1);
app.get('/api/whoami', (req, res) => {
// trust proxy 설정이 올바르면 req.ip는 실제 클라이언트 IP
const clientIp = req.ip;
// 헤더 전체를 직접 읽을 경우 — 검증 없이 사용 금지
const rawForwarded = req.headers['x-forwarded-for'];
res.json({
clientIp,
rawForwarded,
// 신뢰 프록시 수를 초과한 헤더 값은 신뢰하지 않는다
warning: rawForwarded && rawForwarded.includes(',')
? '체인에 여러 프록시가 존재합니다. trust proxy 설정을 확인하세요.'
: null,
});
});
app.listen(3000);
app.set('trust proxy', 1) 한 줄이 전부처럼 보이지만, 프록시 레이어가 추가되거나 제거될 때 이 숫자를 업데이트하지 않으면 IP 추출이 틀어집니다. 저희 팀은 이 값을 환경변수로 외부 주입해 배포 설정에 명시적으로 관리합니다.
보안 역할 — 어디를 막고 어디를 열어야 하는가
리버스 프록시의 가장 중요한 보안 기여 중 하나는 오리진 서버의 IP를 인터넷에 노출하지 않는 것입니다. 오리진 서버의 IP가 공개되지 않으면 운영자는 방화벽에서 리버스 프록시의 IP만 허용하고 나머지 인바운드 트래픽을 전부 차단할 수 있습니다. 오리진으로의 직접 접근 경로가 닫힙니다.
단, 이 보호의 한계도 명확히 이해해야 합니다. DNS 설정 실수, 서버 응답에 포함된 IP 누출, 과거 DNS 캐시 등을 통해 오리진 IP가 외부에 알려질 수 있습니다. 따라서 오리진 IP 은닉은 "보안의 전부"가 아니라 "심층 방어(Defense in Depth)"의 한 레이어로 이해해야 합니다.
WAF(Web Application Firewall, 웹 애플리케이션 방화벽)는 대부분 리버스 프록시와 함께 구성됩니다. WAF는 L7 트래픽을 검사해 SQL 인젝션, XSS(Cross-Site Scripting) 시도를 탐지하고 차단합니다. 리버스 프록시가 트래픽을 받아 WAF로 통과시키거나, WAF 기능이 프록시에 통합된 형태(Nginx + ModSecurity, Cloudflare WAF)로 구성됩니다.
DMZ(Demilitarized Zone, 비무장지대) 아키텍처는 리버스 프록시를 인터넷과 내부망 사이의 완충 지대에 배치합니다.
인터넷
│
▼
[방화벽 - 외부]
│ 443/80 포트만 허용
▼
[리버스 프록시 / WAF] ← DMZ 구간
│ 내부 포트(예: 8080)만 허용
▼
[방화벽 - 내부]
│
▼
[애플리케이션 서버] ← 내부망
[데이터베이스 서버] ← 내부망 (별도 서브넷)
이 구조에서 방화벽 허용 목록은 명확합니다. 외부 방화벽은 인터넷 → 리버스 프록시로 오는 443/80 포트만 허용합니다. 내부 방화벽은 리버스 프록시 → 앱 서버로 오는 내부 서비스 포트만 허용합니다. 앱 서버는 인터넷에서 직접 접근하는 경로가 없습니다. 데이터베이스 서버는 앱 서버 서브넷에서 오는 접근만 허용하는 별도 서브넷에 격리합니다.
대규모 트래픽 급증에 대한 방어도 리버스 프록시 레벨에서 먼저 이루어집니다. 앞서 설명한 Rate Limiting이 첫 번째 완화 계층이고, Cloudflare 같은 CDN 기반 리버스 프록시는 엣지 레벨에서 추가 완화 레이어를 제공합니다.
리버스 프록시 vs. API 게이트웨이 vs. CDN — 어디서 겹치고 어디서 갈라지는가
세 가지 개념이 각각 "리버스 프록시다"라고 소개되다 보니, 실무에서 도입 결정을 내릴 때 혼란이 생깁니다. 겹치는 기능과 갈라지는 기능을 정확히 구분하면 선택이 명확해집니다.
| 기능 | 리버스 프록시 | API 게이트웨이 | CDN |
|---|---|---|---|
| SSL 터미네이션 | O | O | O |
| 로드밸런싱 | O | O | O (엣지 POP 내부) |
| 응답 캐싱 | O | 제한적 | O (정적 자산 특화) |
| 헤더 조작 | O | O | 제한적 |
| 요청 라우팅 | URL/헤더 기반 | URL/헤더/버전 기반 | 지리 기반 라우팅 추가 |
| 인증/인가 처리 | X | O (JWT, OAuth2, API Key) | X |
| 요청/응답 변환 | 제한적 | O (페이로드 변환 포함) | X |
| 쿼터/과금 관리 | X | O | X |
| Rate Limiting | O | O | O |
| 지리적 분산 엣지 POP | X | X | O |
| 정적 자산 특화 최적화 | X | X | O |
| 운영 복잡도 | 낮음 | 중간~높음 | 낮음 (관리형) |
리버스 프록시는 가장 단순하고 범용적입니다. 별도 비즈니스 로직 없이 트래픽을 올바른 백엔드로 전달하고, SSL, 로드밸런싱, 기본 헤더 처리를 담당합니다.
API 게이트웨이는 리버스 프록시 위에 API 관리 기능을 얹은 것입니다. JWT(JSON Web Token, JSON 웹 토큰) 검증, OAuth2 인증, API 키 관리, 요청·응답 페이로드 변환, 개발자 포털, 쿼터 과금 — 이런 기능이 필요하다면 순수 리버스 프록시로는 부족합니다. Kong, AWS API Gateway, Apigee가 여기 해당합니다.
CDN(Content Delivery Network, 콘텐츠 전달 네트워크)은 리버스 프록시 기능을 지리적으로 분산된 엣지 PoP(Point of Presence, 접속 거점)에서 실행합니다. 서울에서 미국 오리진 서버까지 200ms가 걸리던 정적 자산을 서울 PoP 캐시에서 5ms에 응답하도록 만드는 것이 CDN의 본질입니다. Cloudflare, AWS CloudFront, Akamai가 대표적입니다.
선택이 막힐 때는 아래 질문에 차례로 답해보면 됩니다.
- "백엔드로 요청을 전달하고 SSL만 처리하면 충분한가?" → 리버스 프록시 (Nginx, HAProxy)
- "API별 인증, 쿼터, 버전 관리가 필요한가?" → API 게이트웨이
- "전 세계 사용자에게 정적 자산을 빠르게 제공해야 하는가?" → CDN
- "위 세 가지가 모두 필요한가?" → CDN(앞단) + API 게이트웨이(중간) + 리버스 프록시(오리진 앞)의 계층 구성
세 가지를 모두 쌓는 아키텍처가 복잡해 보이지만, 각 레이어의 책임이 명확하기 때문에 장애 지점을 특정하기가 오히려 쉽습니다. Nginx·HAProxy의 실제 설정으로 넘어갈 준비가 됐다면 Nginx·HAProxy로 구축하는 리버스 프록시 실전 설정 가이드(2부)에서 이어서 다룹니다.
리버스 프록시의 원리를 개념 수준에서 이해하면 설정 파일의 각 지시어가 "왜 여기 있는지"가 보이기 시작합니다. proxy_pass, X-Forwarded-For 설정, ssl_certificate, 업스트림 가중치 — 모두 이 글에서 다룬 원리를 그대로 설정으로 옮긴 것입니다. 개념 없이 설정 파일을 복붙하면 트러블슈팅할 때 막막해지고, 원리를 잡고 나면 설정이 따라옵니다. 2부에서는 Nginx와 HAProxy의 실제 설정 파일 예제와 함께, 로드밸런서 Health Check, SSL 인증서 자동 갱신, 접근 로그 구조화를 실전 코드로 다룹니다.
실무 체크리스트
1부 원리를 실제 설정에 연결하기 전에 확인해야 할 항목들입니다.
- SSL 처리 패턴 결정: 컴플라이언스 요건에 따라 Edge Termination / Re-encryption / Passthrough 중 명시적으로 선택한다.
-
trust proxy설정 관리: Express 등 애플리케이션에서trust proxy값을 환경변수로 외부 주입하고, 프록시 레이어 변경 시 함께 업데이트한다. -
X-Forwarded-For주입 방어: 백엔드에서 이 헤더를 직접 파싱한다면 신뢰 프록시 수에 맞게 오른쪽에서 N개를 제거한 뒤 사용한다.req.headers['x-forwarded-for']를 무조건 신뢰하지 않는다. - L4 vs L7 레이어 명시: 팀 내 인프라 문서에 각 구성 요소가 어느 레이어에서 동작하는지 기록해 둔다. 계층이 명확해야 헤더 조작·로깅 책임 소재가 분명해진다.
- 오리진 IP 보호: 리버스 프록시 도입 후 방화벽 규칙에서 오리진 서버의 인바운드를 프록시 IP만 허용하도록 갱신했는지 배포 체크리스트에 포함한다.