프록시 서버와 리버스 프록시

프록시 서버와 리버스 프록시

로컬에서 혼자 웹 앱을 개발하던 사람이 회사 운영 환경을 처음 만지면 꼭 듣게 되는 말이 있어요. “앞단에 nginx를 둘 거예요”라든지, “프록시 통해서 바깥으로 나가야 해요” 같은 문장인데요. 두 쪽 다 “프록시”라는 단어가 들어가는데, 가리키는 대상이 아예 반대입니다. 앞의 것은 리버스 프록시, 뒤의 것은 포워드 프록시예요.

이 글에서는 두 프록시가 어떻게 다른지, 왜 같은 이름을 쓰면서 역할은 서로 반대인지, 실무에서 어디에 어떻게 배치되는지를 차근차근 풀어보려 합니다.

프록시가 대체 뭐였죠?

프록시(proxy)라는 단어는 사전을 찾아보면 “대리인”으로 나옵니다. 네트워크에서는 클라이언트와 서버 사이에 끼어 요청을 대신 전달해주는 중계 서버를 가리켜요. 그런데 “누구의 대리인이냐”에 따라 포워드 프록시와 리버스 프록시로 갈립니다.

클라이언트가 “내가 직접 서버로 간다”가 아니라 “내 대리인이 대신 가준다”로 구조가 바뀌면 포워드 프록시이고요. 서버가 “내가 직접 받는다”가 아니라 “내 대리인이 먼저 받고 나한테 넘긴다”로 바뀌면 리버스 프록시입니다. 이 두 줄만 머리에 넣어두면 헷갈릴 일이 거의 없어요.

포워드 프록시는 클라이언트 편입니다

우리가 흔히 그냥 “프록시 서버”라고 부르는 것은 대부분 포워드 프록시를 가리킵니다. 여러 클라이언트가 인터넷으로 나갈 때 공통의 출구 역할을 해주는 서버예요.

회사 네트워크를 떠올리시면 이해가 쉽습니다. 사내에서 웹을 쓰는 모든 직원의 요청이 일단 회사의 프록시 서버로 들어갑니다. 프록시 서버는 그 요청을 자기 IP로 바꿔 바깥 인터넷으로 내보내고요. 바깥 서버 입장에서는 수백 명의 직원이 아니라 회사 프록시 하나만 다녀간 것처럼 보입니다.

포워드 프록시 흐름
[직원 PC들] → [회사 프록시] → [인터넷]

이 구조에서 얻는 이점이 몇 가지 있어요.

일단 접속 제어가 가능해집니다. 특정 사이트를 차단하거나 업무 시간대에만 허용하는 식으로 기업이 인터넷 사용 정책을 일괄 적용할 수 있거든요. 캐싱도 얹을 수 있습니다. 같은 리소스를 여러 직원이 받아갈 때 한 번만 바깥에서 가져와 나머지는 프록시가 돌려주면 되니까요. 익명성도 빼놓을 수 없어요. 최종 서버는 프록시의 IP만 보게 되니 개별 클라이언트의 IP는 노출되지 않습니다. VPN이나 Tor 같은 익명화 도구도 상당 부분이 포워드 프록시 개념의 확장이라고 보시면 됩니다.

여기서 중요한 건 “클라이언트가 프록시의 존재를 알고 있다”는 점입니다. 브라우저 설정이나 시스템 네트워크 설정에 프록시 주소를 직접 적어두어야 동작하거든요. 즉 포워드 프록시는 클라이언트가 자발적으로 선택해서 거쳐 가는 문입니다.

리버스 프록시는 서버 편입니다

리버스 프록시는 이름에서 짐작되듯 방향이 반대입니다. 사용자의 요청이 최종 애플리케이션 서버에 도달하기 전에 중간에서 먼저 받아주는 서버를 말해요.

리버스 프록시 흐름
[사용자들] → [리버스 프록시] → [내부 앱 서버들]

nginx, HAProxy, Envoy 같은 이름이 리버스 프록시 자리에 자주 올라옵니다. 클라우드 영역으로 가면 AWS ALB나 Cloudflare 에지 같은 관리형 서비스도 같은 자리에 앉고요.

사용자 입장에서는 리버스 프록시의 존재를 전혀 모릅니다. “api.example.com”에 요청을 보냈을 뿐이니까요. 그 뒤에 컨테이너가 열 개든 한 개든, 어떤 버전의 앱 서버를 붙여놨든 사용자에게는 보이지 않습니다. 사용자는 공개 엔드포인트 하나만 알면 되고, 뒷단을 어떻게 배치할지는 운영자의 자유가 됩니다.

이 구조에서 얻는 이점은 포워드 프록시와는 결이 꽤 다릅니다.

대표적으로 떠오르는 건 로드 밸런싱이에요. 동일한 앱 서버 여러 대에 요청을 골고루 뿌려 부하를 나눕니다. 이 둘이 어떻게 겹치고 어디에서 갈리는지가 궁금하다면 로드 밸런서와 리버스 프록시의 차이에서 따로 정리해 두었으니 함께 보시면 좋습니다. SSL/TLS 종단 처리를 리버스 프록시에 맡기면 개별 애플리케이션은 평문 HTTP만 상대해도 되고요. 보안 경계 역할도 큰 몫을 합니다. 공격자는 리버스 프록시의 공개 면만 볼 수 있기 때문에 내부 서버의 실제 위치나 포트를 감출 수 있거든요. 정적 파일 캐싱이나 gzip/brotli 압축, HTTP/2 같은 최신 프로토콜 종단까지 리버스 프록시에서 흡수하고 나면 뒷단의 복잡도가 확 줄어듭니다.

같은 “프록시”인데 왜 방향이 반대일까

두 개념이 헷갈리는 가장 큰 이유는 이름이에요. 둘 다 프록시라고 부르니까요.

그런데 “누구의 대리인인가”를 기준으로 보면 깔끔하게 갈립니다.

포워드 프록시는 클라이언트의 대리인입니다. 사용자가 “나 대신 저 사이트에 다녀와줘”라고 부탁하는 구조예요. 서버는 프록시가 중간에 있다는 걸 모르고, 프록시가 직접 요청한 것처럼 보이죠.

리버스 프록시는 서버의 대리인입니다. 운영자가 “내 앱을 대표해서 네가 먼저 응답해줘”라고 세워둔 것이고요. 클라이언트는 프록시가 중간에 있다는 걸 모르고, 프록시가 직접 응답한 것처럼 보입니다.

그래서 포워드 프록시는 보통 클라이언트 쪽 네트워크에 설정되고, 리버스 프록시는 서버 쪽 인프라에 배치돼요. 같은 중계자라도 바라보는 방향이 반대니 이름 앞에 “reverse”가 붙은 것입니다.

헤더에 남는 흔적

리버스 프록시가 중간에 끼면 서버 관점에서는 원래 클라이언트의 정보가 사라져 보입니다. 모든 요청이 리버스 프록시의 IP에서 오는 것처럼 들어오거든요.

이 문제를 메우려고 관례적으로 쓰는 헤더가 X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host 같은 것들입니다. 각 헤더의 구체적인 형식과 위조 방지 검증 요령은 HTTP 요청의 출처를 알려주는 헤더들에 정리해 두었으니 같이 읽어보시면 좋아요.

리버스 프록시를 거친 요청
GET /users/42 HTTP/1.1
Host: api.example.com
X-Forwarded-For: 203.0.113.19
X-Forwarded-Proto: https

X-Forwarded-For의 첫 번째 IP가 실제 사용자의 IP이고, 뒤에 쉼표로 이어지는 값들은 요청이 거쳐온 프록시들의 IP입니다. 애플리케이션이 사용자 IP로 rate limit을 걸거나 감사 로그를 남기려면 이 헤더를 올바르게 읽어야 해요.

다만 이 헤더는 누구나 위조해서 보낼 수 있어 검증이 필수입니다. 신뢰하는 리버스 프록시에서 온 요청일 때만 X-Forwarded-For를 믿어야 하고요. 외부에서 바로 들어온 요청에 이 헤더가 이미 붙어 있다면 공격자가 IP를 속이려는 시도일 가능성이 큽니다.

실무에서는 어떻게 조합할까

실제 배포 환경을 보면 포워드 프록시와 리버스 프록시가 한 요청 안에서 함께 등장하는 일이 많습니다.

사내 서비스가 외부 결제사 API를 호출한다고 가정해봐요. 나가는 트래픽은 회사의 포워드 프록시를 지나 바깥으로 나갑니다. 결제사에 도착한 요청은 그쪽 에지 네트워크를 거쳐 리버스 프록시를 타고 최종 애플리케이션으로 전달되고요.

한 요청에 두 종류의 프록시
[앱 컨테이너]
  → [사내 포워드 프록시]
  → [인터넷]
  → [결제사 에지]
  → [결제사 리버스 프록시]
  → [결제사 애플리케이션]

위 경로에서 사내 포워드 프록시는 우리가 통제하는 출구이고, 결제사 리버스 프록시는 상대가 통제하는 입구입니다. 둘 다 “프록시”이긴 하지만 관리 주체와 목적이 완전히 다르죠.

최근에는 제로 트러스트 보안 모델이 이 구도를 조금 더 복잡하게 만들고 있어요. 기업 내부 서비스를 Cloudflare Access 같은 외부 리버스 프록시 뒤에 숨기면서 사용자별로 인증을 강제하는 방식이 늘고 있고요. 내부 서버가 방화벽에 포트를 열지 않고 외부 터널 서비스로 아웃바운드 연결을 먼저 맺어두는 Cloudflare Tunnel 같은 구조도 빠르게 자리 잡고 있습니다. 전통적인 포트 포워딩 없이도 리버스 프록시의 역할을 클라우드 쪽에서 대신 수행하는 셈이에요.

마치며

프록시 서버와 리버스 프록시 서버는 이름이 같지만 대리하는 대상이 서로 다른 중계자입니다. 포워드 프록시는 클라이언트를 위해 바깥으로 나가는 문을 대신 열어주고, 리버스 프록시는 서버를 대신해 바깥 요청을 먼저 받아줍니다.

어느 쪽이든 중간자가 끼어 있다는 사실은 변하지 않아요. 그래서 네트워크 문제가 생겼을 때 “중간에 뭐가 끼어 있는지” 파악하는 일이 디버깅의 출발점이 되고요. 헤더에 남는 흔적을 읽는 능력과 팀 안에서 프록시의 방향과 주체를 정확한 언어로 이야기하는 연습을 같이 해두면 운영 환경에서의 의사소통이 훨씬 매끄러워집니다.

HTTP 프록시 동작의 세부 스펙은 RFC 9110 HTTP Semantics에 정리되어 있으니 더 파고들고 싶을 때 참고하세요.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord