업데이트됨 1개월 전
웹사이트를 방문할 때, 당신은 그 서버와 직접 대화한다고 생각합니다. 아마 그렇지 않을 겁니다. 당신은 리버스 프록시와 대화하고 있습니다 — 실제로는 당신의 요청을 다른 곳으로 전달하면서도 진짜인 척하는 서버입니다.
클라이언트는 실제 서버와 대화한다고 생각합니다. 그렇지 않습니다. 그게 핵심입니다.
모든 것을 가능하게 하는 속임수
일반 프록시(때로는 "포워드 프록시"라고도 불립니다)는 클라이언트를 대신해 동작합니다 — 웹 페이지를 대신 가져와 웹사이트가 당신의 IP 대신 프록시 IP를 보도록 하는 VPN처럼요. 프록시는 당신을 위해 일합니다.
리버스 프록시는 이 관계를 뒤집습니다. 서버를 대신해 동작합니다. "리버스"는 방향에 관한 것이 아니라 — 누구를 위해 프록시가 일하느냐에 관한 것입니다. 포워드 프록시는 서버로부터 클라이언트를 숨깁니다. 리버스 프록시는 클라이언트로부터 서버를 숨깁니다.
이 속임수가 이후의 모든 것을 가능하게 합니다: 로드 밸런싱, 캐싱, 보안, SSL 종료. 클라이언트가 커튼 뒤에서 무슨 일이 일어나는지 모르고 — 알 필요도 없기 때문에 — 이 모든 것이 작동합니다.
요청을 보낼 때 어떤 일이 일어나는가
브라우저는 웹 서버라고 믿는 곳에 요청을 보냅니다. 요청은 대신 리버스 프록시에 도착합니다.
리버스 프록시는 당신의 요청을 검토합니다 — URL 경로, 헤더, 아마도 내용까지 — 그리고 어느 백엔드 서버가 처리해야 할지 결정합니다. 요청을 그쪽으로 전달하면서, 헤더를 수정하거나 인증 정보를 추가할 수도 있습니다.
백엔드 서버가 요청을 처리하고 리버스 프록시로 응답을 돌려보냅니다. 프록시는 그 응답을 캐시하거나, 압축하거나, 헤더를 수정하거나, 그냥 통과시킬 수 있습니다. 그런 다음 원본 서버에서 직접 온 것처럼 당신에게 응답을 보냅니다.
당신은 백엔드 서버를 볼 수 없습니다. 당신이 아는 것은 리버스 프록시의 주소뿐입니다. 실제 애플리케이션 서버들은 이동하거나, 늘어나거나, 완전히 바뀔 수 있습니다 — 당신은 절대 알 수 없습니다.
이 아키텍처가 존재하는 이유
현대 웹 애플리케이션은 단일 서버가 아닙니다. 애플리케이션 서버, 데이터베이스 서버, 캐싱 계층, 마이크로서비스의 클러스터입니다. 누군가 클라이언트가 이 복잡성에 어떻게 연결하는지 관리해야 합니다.
그 누군가가 리버스 프록시입니다. 다음을 제공합니다:
단일 진입점 — 뒤에서 몇 개의 서버가 실행되든 상관없이. 클라이언트는 하나의 주소로 연결합니다. 그 이후에 무슨 일이 일어나는지는 당신의 문제지, 그들의 문제가 아닙니다.
부하 분산 — 여러 서버에 걸쳐. 애플리케이션 서버가 세 개? 리버스 프록시는 각 요청을 여유 있는 서버로 보냅니다. 서버 하나가 실패? 프록시가 자동으로 우회합니다.
인프라 유연성. 서버를 추가하고, 제거하고, 이동할 수 있습니다 — 클라이언트는 절대 알 수 없습니다. 요청은 여전히 같은 주소로 갑니다.
보안 경계. 백엔드 서버는 공개 IP 주소가 필요하지 않습니다. 오직 리버스 프록시만 인터넷을 마주합니다. 이는 공격 표면을 크게 줄입니다.
성능 최적화. 프록시는 응답을 캐시하고, 콘텐츠를 압축하고, SSL을 종료할 수 있습니다 — 모든 백엔드 서버에 부담을 줄 작업들을 대신 처리합니다.
로드 밸런싱
여러 백엔드 서버가 있을 때, 누군가 각 요청을 어디서 처리할지 결정해야 합니다. 리버스 프록시가 다양한 알고리즘을 사용해 이 선택을 합니다:
라운드 로빈은 요청을 서버에 순서대로 보냅니다: 먼저 서버 A, 다음은 B, 그 다음 C, 다시 A로.
최소 연결은 각 요청을 현재 활성 연결이 가장 적은 서버로 보냅니다.
가중치 분산은 더 강력한 서버로 더 많은 요청을 보냅니다. 서버 A가 서버 B보다 두 배 용량이라면, 두 배의 트래픽을 받습니다.
일관성 해싱은 같은 클라이언트(또는 같은 리소스)의 요청이 같은 서버로 가도록 합니다. 서버가 상태를 유지할 때 중요합니다.
이렇게 하면 수평 확장이 가능해집니다 — 더 많은 용량이 필요한가요? 서버를 더 추가하세요. 리버스 프록시가 부하를 분산시킵니다.
SSL 종료
HTTPS 암호화는 계산 비용이 높습니다. 모든 암호화 연결에는 암호화 연산이 필요합니다.
SSL 종료를 사용하면, 리버스 프록시가 모든 HTTPS 협상을 처리합니다. 클라이언트는 프록시에 안전하게 연결합니다. 프록시는 그런 다음 백엔드 서버와 일반 HTTP로 통신합니다(보안 요구 사항이 내부 암호화도 요구한다면 HTTPS로도 통신합니다).
이는 인증서 관리를 중앙화합니다 — 모든 백엔드 서버 대신 한 곳에서 인증서를 설치하고 갱신합니다. 암호화 연산에 최적화된 특수 하드웨어나 소프트웨어를 사용할 수 있게 해줍니다. 그리고 백엔드 서버가 암호화 대신 애플리케이션 로직에 집중할 수 있게 해줍니다.
캐싱
수백 명의 사용자가 같은 리소스를 요청할 때, 왜 수백 번 생성해야 할까요?
리버스 프록시는 응답을 캐시할 수 있습니다. 첫 번째 요청은 백엔드 서버에 도달합니다. 같은 리소스에 대한 이후 요청은 프록시에서 직접 캐시된 응답을 받습니다 — 백엔드 서버는 그것을 볼 일이 없습니다.
정적 콘텐츠 — 이미지, CSS, JavaScript — 에는 적극적인 캐싱으로 백엔드 서버가 각 파일을 한 번만 제공합니다. 어느 정도 오래된 데이터를 허용하는 동적 콘텐츠의 경우, 짧은 캐시 기간도 백엔드 부하를 크게 줄입니다.
프록시는 백엔드 서버의 Cache-Control 헤더를 따르므로, 무엇이 얼마나 오래 캐시될지는 애플리케이션이 제어합니다. 콘텐츠가 변경되면, 캐시 무효화로 오래된 응답이 제거됩니다.
보안 기능
리버스 프록시는 문지기입니다. 모든 요청이 그것을 통과하므로, 보안을 시행하기에 자연스러운 장소입니다.
백엔드 보호: 애플리케이션 서버는 공개 IP 주소가 필요하지 않습니다. 프록시를 통해서만 접근 가능한 사설 네트워크에 존재합니다. 주소를 알 수 없으면 공격도 할 수 없습니다.
요청 필터링: 프록시는 SQL 인젝션 시도, 크로스 사이트 스크립팅, 또는 다른 악의적인 패턴을 요청에서 검사할 수 있습니다. 애플리케이션에 도달하기 전에 차단합니다.
속도 제한: 클라이언트가 초당 또는 분당 보낼 수 있는 요청 수를 제한합니다. 이는 무차별 대입 공격, 리소스 고갈, 기본적인 서비스 거부 시도를 방지합니다.
정보 숨기기: 서버 버전 헤더를 제거하고, 오류 메시지를 정리하고, 백엔드 아키텍처를 드러내는 모든 응답 데이터를 제거합니다. 공격자가 당신의 시스템을 파악하는 데 도움을 주지 마세요.
중앙화된 인증: 요청이 백엔드 서버에 도달하기 전에 프록시에서 사용자를 인증합니다. 프록시 뒤의 모든 서비스는 직접 구현 없이 일관된 인증을 받습니다.
상태 확인 및 장애 조치
로드 밸런서는 죽은 서버로 요청을 보내면 무용지물입니다. 리버스 프록시는 백엔드 상태를 모니터링합니다.
능동적 상태 확인은 주기적으로 각 백엔드 서버를 점검합니다 — TCP 연결 시도나 상태 엔드포인트에 HTTP 요청을 보낼 수도 있습니다. 올바르게 응답하지 않는 서버는 비정상으로 표시됩니다.
수동적 상태 확인은 실제 트래픽을 모니터링합니다. 서버가 오류를 반환하거나 타임아웃이 발생하기 시작하면, 프록시가 이를 알아채고 트래픽 전송을 중단합니다.
백엔드 서버가 실패하면, 프록시는 자동으로 우회합니다. 요청은 정상 서버로 가기 때문에 계속 성공합니다. 실패한 서버가 복구되면, 순환에 복귀합니다. 수동 개입이 필요하지 않습니다.
주요 솔루션
Nginx는 리버스 프록시 분야의 강자입니다. 빠르고, 동시 연결에 효율적이며, 설정이 간단합니다. 대부분의 현대 웹 애플리케이션이 사용합니다.
HAProxy는 로드 밸런싱에 특화되어 있습니다. 정교한 알고리즘, 세부적인 상태 확인, 높은 부하에서도 뛰어납니다. 분산 로직이 주요 관심사일 때 선택하세요.
Traefik은 컨테이너 오케스트레이션과 통합됩니다. Docker나 Kubernetes에서 서비스를 자동으로 발견하고 라우팅을 설정합니다. 마이크로서비스 배포에서 인기 있습니다.
Envoy는 서비스 메시 아키텍처를 구동합니다. 고성능, 서킷 브레이킹, 상세한 가시성 같은 고급 기능을 갖추고 있습니다. 많은 클라우드 네이티브 시스템의 데이터 플레인 프록시입니다.
Caddy는 최소한의 설정으로 자동 HTTPS를 제공합니다. 단순함이 가장 중요한 소규모 배포에 탁월합니다.
리버스 프록시 vs. 로드 밸런서
대부분의 리버스 프록시가 로드 밸런싱을 하고 대부분의 로드 밸런서가 리버스 프록시를 하기 때문에 용어가 겹칩니다.
개념적으로: 로드 밸런서는 서버 간 요청 분산에 집중합니다. 리버스 프록시는 요청과 응답을 수정하고, 콘텐츠를 캐시하고, SSL을 처리하고, URL 기반으로 라우팅할 수 있는 중개자 역할에 집중합니다.
실제로, Nginx와 HAProxy는 둘 다 합니다. 시스템을 설계할 때 구분이 중요합니다 — 주로 분산 문제를 해결하려는 건지, 중개자 문제를 해결하려는 건지 — 하지만 동일한 소프트웨어가 둘 다 처리합니다.
설정 예시
기본적인 Nginx 리버스 프록시 설정:
세 개의 백엔드 서버. 자동으로 로드 밸런싱됩니다. 클라이언트 IP가 헤더에 전달되어 백엔드가 실제로 누가 요청하는지 알 수 있습니다. 정적 콘텐츠는 한 시간 동안 캐시됩니다.
마이크로서비스 아키텍처에서
애플리케이션이 수십 개의 서비스로 분해되면, 리버스 프록시는 더욱 중요해집니다.
API 게이트웨이는 마이크로서비스에 특화된 리버스 프록시입니다. 클라이언트 요청을 올바른 서비스로 라우팅하고, 여러 서비스의 응답을 집계하고, 인증을 처리하고, 속도 제한을 구현합니다.
서비스 메시는 모든 서비스 옆에 프록시 사이드카를 배포합니다. 각 서비스는 로컬 프록시와 통신하며, 프록시가 모든 네트워크 통신을 처리합니다: 서비스 발견, 로드 밸런싱, 암호화, 재시도, 타임아웃. 모든 서비스 간 호출에 적용된 리버스 프록시 패턴입니다.
보이지 않는 인프라
리버스 프록시는 보이지 않음으로써 성공합니다. 제대로 작동할 때, 당신은 그것이 거기 있다는 것을 알지 못합니다. 요청이 도착하고, 처리되고, 반환됩니다 — 그 사이에 일어난 복잡성은 숨겨진 채로 남습니다.
그 보이지 않음이 핵심입니다. 클라이언트는 세 개의 애플리케이션 서버, 캐싱 계층, SSL 인증서, 상태 확인에 대해 알 필요가 없습니다. 클라이언트에게는 응답만 있으면 됩니다.
리버스 프록시는 클라이언트가 보는 것은 아무것도 바꾸지 않으면서 그 뒤의 모든 것을 바꿀 수 있는 유연성을 주며 그것을 가능하게 합니다.
리버스 프록시에 관한 자주 묻는 질문
리버스 프록시를 사용하면 지연 시간이 늘어나나요?
네, 하지만 일반적으로 마이크로초에서 한 자릿수 밀리초 수준입니다 — 캐싱, 압축, 효율적인 부하 분산으로 얻는 지연 시간 절감에 비하면 무시할 수 있는 수준입니다. 잘 설정된 리버스 프록시는 추가 홉에도 불구하고 거의 항상 전체 응답 시간을 개선합니다.
백엔드 서버가 하나뿐일 때도 리버스 프록시를 사용할 수 있나요?
물론입니다. 백엔드가 하나뿐이어도 SSL 종료, 캐싱, 압축, 요청 필터링, 그리고 나중에 클라이언트 측 설정을 변경하지 않고도 서버를 더 추가할 수 있는 능력을 얻습니다.
리버스 프록시와 CDN의 차이점은 무엇인가요?
CDN은 본질적으로 전 세계에 분산된 리버스 프록시 네트워크입니다. CDN 에지 서버는 전 세계 사용자 가까이에 콘텐츠를 캐시합니다. 리버스 프록시는 일반적으로 자체 인프라 내, 자체 서버 앞에 위치합니다. 많은 아키텍처가 둘 다 사용합니다: 에지에는 CDN, 데이터 센터에는 리버스 프록시.
리버스 프록시는 원래 클라이언트의 IP 주소를 어떻게 알 수 있나요?
자동으로는 알 수 없습니다 — 클라이언트의 연결이 아닌 백엔드로의 자체 연결만 볼 수 있습니다. 그래서 설정에 X-Real-IP와 X-Forwarded-For 같은 헤더가 포함됩니다. 프록시는 원래 클라이언트 IP를 백엔드에 알리기 위해 이 헤더를 추가합니다.
백엔드 서버는 X-Forwarded-For 헤더를 신뢰해야 하나요?
요청이 리버스 프록시를 통해 왔을 때만요. 이 헤더는 백엔드에 직접 연결하는 클라이언트에 의해 위조될 수 있습니다. 신뢰할 수 있는 프록시 IP 주소에서 온 경우에만 이 헤더를 수락하도록 백엔드를 설정하세요.
이 페이지가 도움이 되었나요?