프록시 Proxy - 왜 대규모 트래픽 서비스는 직접 연결하지 않을까?
수천만 사용자가 접속하는 서비스에서 직접 연결은 오히려 독이다.
넷플릭스, 우버, 아마존과 같은 글로벌 테크 기업들은 공통적으로 '프록시 컴포넌트(proxy component)'를 적극 활용합니다.
그런데, 왜일까요?
단순히 트래픽을 중간에서 전송만 해주는 존재라고 보기엔, 이들이 투자한 노력과 최적화 전략이 너무 정교합니다.
프록시란 무엇인가?
프록시(proxy)란, 사용자의 요청을 실제 서비스나 서버에 전달하기 전에 중간에서 가로채거나 가공하여 전달하는 컴포넌트를 말합니다. 프록시는 단순한 중계기가 아닙니다. 요청을 필터링하거나, 캐싱하거나, 라우팅하거나, 인증을 추가하는 등 다양한 기능을 수행합니다. 시스템 디자인에서 프록시는 다음과 같은 형태로 자주 등장합니다
API Gateway
외부 요청을 수집하고, 인증과 라우팅, 응답 포맷 변환 등을 담당
Reverse Proxy
클라이언트 요청을 여러 백엔드 서버로 분산
Caching Proxy
자주 쓰는 데이터를 미리 저장해 응답 속도 향상
Service Mesh Sidecar Proxy
마이크로서비스 간 통신의 제어와 보안을 담당
이러한 프록시들은 단순한 기술 컴포넌트가 아니라, 시스템의 복잡도를 제어하고 안정성과 확장성을 높이는 핵심 도구입니다.
프록시 도입의 트레이드오프는 무엇인가?
프록시를 도입하면 구조가 더 복잡해집니다. 모든 요청이 프록시를 거쳐야 하기 때문에, 프록시 자체가 병목이나 SPOF(Single Point of Failure)가 될 수 있습니다.
또한 다음과 같은 트레이드오프가 존재합니다
중앙 집중형 프록시 vs 사이드카 프록시
중앙 집중형 프록시
모든 트래픽을 한 곳(API Gateway, ALB 등)에서 통제
설정과 관리가 한 곳에서 이루어지므로 운영이 단순함
하지만, 내부 마이크로서비스 간 복잡한 통신 제어나 팀별 유연한 정책 적용에는 한계
넷플릭스 Zuul, Amazon API Gateway가 대표적인 예
사이드카 프록시
각 마이크로서비스 인스턴스마다 별도 프록시가 붙음 (Envoy, Istio 등)
서비스마다 세부 정책을 다르게 설정 가능 (예: 레이트 리밋, 인증, 트래픽 미러링 등)
배포 및 운영 비용이 크고, 수백 개의 프록시를 관리해야 함
Kubernetes 기반 마이크로서비스에서 많이 사용
오픈소스 vs 커스텀 빌드
오픈소스 프록시 (Envoy, NGINX 등)
이미 만들어진 기능을 빠르게 적용 가능
커뮤니티와 문서가 풍부하고, 유지보수와 업그레이드가 쉬움
반면, 복잡한 기업 요구사항을 완전히 만족시키긴 어려움
작은 스타트업이나 빠른 MVP 단계에 적합
커스텀 프록시 (Netflix Zuul 등)
기업이 직접 설계해서 개발
기능, 성능, 장애 처리 방식을 모두 원하는 대로 구현 가능
유지보수와 확장에 대한 책임도 모두 내부에서 감당해야 함
넷플릭스처럼 대규모 트래픽과 특별한 요구사항이 있는 기업이 선택
성능 vs 기능성
성능에 집중한 프록시
역할을 최소화함 (예: 캐시, 단순 라우팅)
응답 속도 빠르고, 시스템 리소스 사용도 낮음
하지만 기능 확장이 필요하면 추가 컴포넌트를 붙여야 함
예: 정적 리소스를 빠르게 서빙하는 CDN 엣지 프록시
기능 중심의 프록시
인증, A/B 테스트, 로깅, QoS 정책 등 다양한 역할을 수행
다기능 통합 구조로 개발자가 다양한 상황에 유연하게 대응 가능
단점은 레이턴시 증가, 복잡도 상승, 장애 포인트 증가
예: Uber의 API Gateway, Envoy + Lua 확장 기반 프록시
시스템 디자인에서 프록시가 필요한 이유
인증 서버가 느려지면 전 서비스가 멈춘다?
당신의 서비스에 로그인 요청이 몰리는 순간, 인증 서버 하나가 느려졌다고 생각해보세요. 결과는? 로그인만 멈추는 것이 아닙니다. 유저들은 페이지 전체가 '먹통'이 되었다고 인식합니다.
넷플릭스는 사용자 인증 요청을 프록시가 선별적으로 처리하며, 내부 인증 서버에 장애가 있어도 외부 트래픽을 잠시 지연시키거나 우회시킬 수 있는 구조를 갖추고 있습니다. 프록시는 인증 실패의 여파가 전체 시스템에 확산되는 것을 막아줍니다.
서버 간 요청 로그 추적이 안 된다?
수십 개 마이크로서비스가 서로 호출하며 작동하는 환경에서, 어느 요청이 어디에서 실패했는지 파악조차 어렵습니다. 예외 로그는 남았지만, 그 흐름이 어떻게 흘렀는지는 보이지 않습니다.
넷플릭스는 이를 위해 프록시 컴포넌트 내부에 Request Passport 라는 기능을 넣어 요청의 흐름을 각 단계마다 추적합니다. Uber는 API Gateway에서 요청 단위의 트레이싱 ID를 강제 부여하여, 문제가 발생했을 때 요청의 이동 경로를 시각적으로 추적할 수 있게 설계했습니다.
프록시와 캐시의 연결고리 - Caching Proxy
프록시는 단순 라우터가 아니다
프록시는 요청을 필터링하고 가공할 수 있는 중간 컴포넌트입니다. 그 중 한 가지 대표적인 기능이 바로 "응답을 캐싱해서 다음 요청을 더 빠르게 처리" 하는 것입니다.
캐시 프록시의 역할
응답 캐싱
사용자의 동일한 요청에 대해 백엔드 서버에 재요청하지 않고, 프록시가 저장해둔 응답을 즉시 반환
부하 완화
DB나 백엔드 서비스가 반복적으로 요청받는 데이터를 줄여 트래픽을 완화
지연 최소화
백엔드까지 가지 않고 프록시 단계에서 처리하면 응답 속도 향상
프록시 캐시 계층 설계
CDN → Edge Proxy → Application Proxy → Backend 순으로 계층적으로 배치 가능
넷플릭스 사례 - EVCache와 Open Connect는 둘 다 프록시 계층에 존재
1. EVCache
Memcached 기반의 캐시 프록시 컴포넌트
넷플릭스의 여러 마이크로서비스 앞단에 위치
API Gateway나 앱 서버에서 직접 DB를 조회하지 않고, EVCache가 먼저 응답
이 자체가 캐시 역할을 수행하는 프록시입니다
2. Open Connect (CDN)
넷플릭스의 자체 콘텐츠 전송 네트워크
각 지역의 ISP에 배치된 프록시 서버가 자주 재생되는 콘텐츠를 저장
사용자가 비디오 재생 요청을 보내면, 넷플릭스 서버가 아닌 가장 가까운 캐시 프록시가 응답
Amazon 사례도 동일
CloudFront = 캐시 프록시
→ HTML, JS, 이미지, 심지어 GraphQL 응답도 캐시할 수 있음ALB와 연동하여 프록시가 동적으로 캐싱 여부를 결정하거나 TTL 정책 적용
캐싱 실패 시 → 원본 요청을 백엔드로 리디렉션하는 것도 프록시의 책임
캐시 위치가 구조를 망칠 수 있는 이유
“프록시는 ‘위치 기반 캐시 전략’을 가능하게 하는 통제 지점이다.”
너무 앞단 캐시 (CDN 수준)
실시간성이 필요한 데이터가 변경되어도 반영이 느림 (예: 가격, 재고)
너무 뒷단 캐시 (DB 바로 앞)
성능 개선 효과가 제한됨. 네트워크/앱서버 병목은 해결 못함적절한 위치의
캐시 프록시
사용자 요청 패턴을 분석해 응답 시간과 부하 절충
넷플릭스는 Open Connect라는 자체 CDN을 통해 사용자 단말기 가까이에 비디오 데이터를 캐싱하고, 애플리케이션 레벨에서는 EVCache라는 메모리 캐시 프록시를 활용해 데이터베이스 부하를 줄입니다. Amazon도 CloudFront로 글로벌 엣지 캐시를 운영하며 ALB와 연동해 동적 요청까지도 처리합니다.
따라서, "캐시 프록시"는 시스템 아키텍처의 핵심입니다. 위치를 어디에 두느냐, 어떤 데이터를 얼마 동안 저장하느냐, 장애 시 어떻게 대응하느냐 모두 프록시 컴포넌트의 역할입니다.
"유저가 버튼을 누른 순간, 5개 마이크로서비스가 호출된다면?"
예를 들어, 사용자가 앱에서 '주문하기' 버튼을 누르면 다음과 같은 호출이 동시에 발생합니다.
주문 생성 서비스
결제 서비스
유저 포인트 서비스
재고 확인 서비스
배송 ETA 계산 서비스
그 중 하나라도 느려지거나 실패하면 전체 요청은 실패합니다. 최악의 경우, 사용자는 돈을 결제했는데 주문이 생성되지 않았다는 불만을 남기게 됩니다.
Uber는 이러한 다중 요청 흐름에 대응하기 위해 API Gateway에서 각 요청마다 적절한 타임아웃, 재시도, 순차 호출 등을 설정할 수 있도록 구성했습니다. 넷플릭스 역시 각 마이크로서비스의 응답 시간 및 오류율을 기반으로 프록시 레이어에서 장애 감지 및 우회 처리를 하도록 설정했습니다.
이 문제를 해결한 기업들의 공통 전략
넷플릭스는 Zuul이라는 자체 API 게이트웨이를 만들어 각 요청에 필터를 걸고, 병목 구간을 미리 감지하며, 장애를 고립시키는 구조를 만들었습니다. Zuul2 에서는 Netty 기반의 논블로킹 처리 모델을 도입해, 초당 수백만 요청을 처리하는 구조로 최적화했습니다.
우버는 Node.js 기반 API 게이트웨이를 수백 개의 마이크로서비스 앞단에 세우고, 사용자가 누른 버튼이 어떤 요청으로 바뀌고, 어느 서비스로 분배되는지를 중앙에서 제어했습니다. 이후 Golang 기반으로 마이그레이션하면서 성능 향상과 개발자 경험 개선을 동시에 달성했습니다.
아마존은 ALB(Application Load Balancer)와 CloudFront, 그리고 API Gateway를 조합하여 각각의 서비스가 트래픽 폭주에도 유연하게 대처할 수 있도록 설계했습니다. CloudFront 엣지 서버에서는 사용자 위치 기반으로 가장 빠른 리전을 선택해 요청을 라우팅하고, ALB는 세부 경로에 따라 마이크로서비스를 정확히 매핑합니다.
이처럼 '프록시 컴포넌트'는 단순한 라우터가 아니라 트래픽 제어, 인증 분리, 장애 고립, 실시간 로깅, 데이터 캐싱의 최적 위치 결정까지 아우르는 핵심 설계 포인트입니다. 그리고 이 핵심은, 단순히 빅테크의 문제만이 아니라 당신의 서비스가 성장할 때 반드시 마주칠 문제이기도 합니다.
시나리오 #1 - 글로벌 쇼핑몰의 API Gateway 프록시
A사는 전 세계에 고객을 둔 쇼핑몰 플랫폼을 운영하고 있습니다. 프론트엔드는 React 기반 웹앱이고, 백엔드는 주문, 결제, 배송, 추천 시스템 등 40여 개의 마이크로서비스로 구성되어 있습니다.
프론트엔드에서 API를 직접 호출하다 보니 백엔드 변경에 따라 앱도 자주 수정해야 함
각 서비스마다 인증 방식, 응답 포맷, 라우팅 경로가 달라 유지보수가 어려움
여러 서비스가 동시에 호출되어야 하는 요청(예: 장바구니 확인 시 결제 가능 상태까지 확인)에서 실패율이 높음
프록시 도입 (API Gateway)
외부에서 오는 모든 요청을 API Gateway 프록시가 먼저 수신
공통적으로 필요한 인증, 요청 검증, 로깅, 라우팅 등을 프록시 레이어에서 처리
프론트엔드는 더 이상 여러 API를 따로 호출하지 않고, Gateway에만 요청
예:
/api/user/orders→ Gateway → 주문 서비스 + 결제 서비스 병렬 호출 → 응답 통합
임팩트
프론트엔드가 훨씬 단순해지고, 백엔드 구조 변경에 유연하게 대응 가능
장애 전파가 줄고, 공통 정책을 중앙에서 쉽게 통제
로깅/트래픽 모니터링을 통합적으로 처리해 디버깅과 보안성 강화
시나리오 #2 실시간 배달 플랫폼의 사이드카 프록시 + 캐시 프록시
B사는 음식 배달 서비스를 운영합니다. 사용자가 앱에서 주문을 요청하면,
위치 기반으로 가까운 라이더를 찾고
예상 도착 시간(ETA)을 계산하고
배달비를 실시간으로 책정합니다.
이 모든 과정은 수 밀리초 단위로 반응해야 하며, 수십 개의 마이크로서비스가 관여합니다.
서비스 간 호출이 많아져서 네트워크 트래픽 과부하 발생
특정 마이크로서비스가 느려지면 전체 응답이 지연됨
장애 발생 시, 어디에서 문제가 생겼는지 파악하기 어려움
ETA 계산, 거리 기반 수수료는 자주 바뀌지 않는데도 매번 계산됨
프록시 도입 (Service Mesh + Caching Proxy)
각 마이크로서비스 옆에 사이드카 프록시(Envoy)를 배치 → 서비스 간 통신을 제어
장애가 발생하면 프록시가 자동으로 재시도하거나 대체 경로로 라우팅
모든 요청은 트레이싱 ID로 연결되어 추적 가능
ETA 계산 API는 캐시 프록시를 앞단에 배치하여, 동일 경로/시간대 요청은 캐시 응답 반환
임팩트
네트워크 장애와 느린 서비스로 인한 문제 격리 가능
장애 발생 시 전체 요청 트레이스 추적 가능
ETA, 배달비 같은 반복 요청은 캐시로 처리해 DB, 연산 부하 감소
사용자 체감 속도 향상 + 시스템 안정성 확보





