사용자는 하나의 도메인으로 접속하지만 뒤에는 여러 애플리케이션 서버가 있을 수 있다. 앞단의 서버는 연결을 받고 요청을 검사하고 처리할 서버 하나를 골라 전달한다.
리버스 프록시(reverse proxy: 클라이언트 앞이 아니라 서버들 앞에서 요청을 대신 받고 내부 서버로 전달하는 중간 서버)와 로드 밸런서(load balancer: 여러 처리 대상에 요청이나 연결을 나누는 구성 요소)는 비슷한 위치에 있지만 강조점이 다르다. 리버스 프록시는 전달·보안·캐시·TLS 종료 같은 기능을, 로드 밸런서는 부하 분산과 장애 대상 제외를 중심으로 설명할 때가 많다. 하나의 제품이 두 역할을 함께 맡기도 한다.
앞단 서버가 연결의 경계를 나눈다
TLS 종료(TLS termination: 앞단 서버가 클라이언트와의 TLS 연결을 끝내고 복호화된 요청을 내부로 전달하는 구성)를 사용하면 인증서와 외부 암호 연결을 한곳에서 관리할 수 있다.
클라이언트
⇄ TLS 연결
리버스 프록시
⇄ 내부 HTTP 또는 별도 TLS
애플리케이션 서버
이때 외부 연결과 내부 연결은 서로 다른 연결이다. 클라이언트가 연결을 끊었다고 내부 요청이 자동으로 취소되는지, 내부 구간도 암호화할지, 원래 IP와 프로토콜을 어떤 헤더로 전달할지 정해야 한다.
프록시가 X-Forwarded-For 같은 헤더를 믿을 때는 신뢰할 프록시가 덧붙인 값인지 확인해야 한다. 외부 클라이언트가 보낸 같은 이름의 헤더를 그대로 신뢰하면 접근 제어와 로그가 틀릴 수 있다.
라운드 로빈은 요청 수를 순서대로 나눈다
라운드 로빈(round robin: 준비된 서버를 순서대로 돌아가며 선택하는 분산 방식)은 이해하기 쉽다.
요청 1 → 서버 A
요청 2 → 서버 B
요청 3 → 서버 C
요청 4 → 서버 A
하지만 요청마다 처리 시간이 다르면 서버의 실제 부하는 고르게 나뉘지 않는다. 긴 요청을 받은 서버 A가 바쁜데도 다음 차례가 돌아올 수 있다.
최소 연결(least connections: 현재 열린 연결이 가장 적은 서버를 고르는 방식)은 연결 수를 부하의 근사치로 쓴다. 가중치(weight: 서버 성능이나 역할에 따라 선택 비율을 조정하는 값)를 두어 큰 서버에 더 많은 요청을 보낼 수도 있다. 어떤 기준이 맞는지는 연결 길이, 요청 비용, 서버 크기에 따라 달라진다.
헬스 체크는 살아 있음과 처리 가능함을 구분해야 한다
헬스 체크(health check: 서버가 요청을 받을 수 있는지 주기적으로 확인하는 검사)가 실패하면 로드 밸런서는 해당 서버를 대상에서 뺄 수 있다.
프로세스가 살아 있는지 확인하는 것과 실제 요청을 처리할 준비가 됐는지는 다르다. 포트는 열렸지만 데이터베이스 연결이 끊겼거나 초기 데이터 로딩이 끝나지 않았을 수 있다.
liveness : 프로세스를 다시 시작해야 할 정도로 망가졌는가
readiness : 지금 새 요청을 보내도 되는가
검사를 너무 깊게 만들면 일시적인 하위 의존성 지연 때문에 모든 서버가 동시에 제외될 수 있다. 너무 얕으면 실패 요청을 계속 보낸다. 어떤 의존성을 준비 상태의 필수 조건으로 볼지 정해야 한다.
세션 고정은 상태 문제를 가릴 수 있다
세션 고정(sticky session: 같은 사용자의 요청을 가능한 한 같은 서버로 보내는 분산 방식)은 서버 메모리에 로그인 세션이나 임시 상태가 있을 때 편리하다. 쿠키나 클라이언트 주소를 기준으로 서버를 고를 수 있다.
하지만 해당 서버가 내려가면 메모리 상태도 함께 사라질 수 있고 특정 사용자 요청이 한 서버에 몰릴 수 있다. 서버 밖의 공유 저장소에 세션을 두거나 상태 없는(stateless: 요청 처리에 필요한 사용자 상태를 특정 서버의 로컬 메모리에 의존하지 않는) 애플리케이션을 만드는 이유다.
세션 고정이 나쁜 기능이라기보다 장애 전환과 확장의 선택을 바꾼다. 왜 필요한지, 서버 교체 때 어떤 상태를 잃는지 분명해야 한다.
재시도는 안전한 요청에서만 대신할 수 있다
프록시는 서버 연결에 실패하면 다른 서버로 요청을 재시도할 수 있다. 읽기 요청이라면 도움이 될 수 있지만 서버가 주문 생성 요청을 이미 처리한 뒤 응답만 끊겼다면 다른 서버에서 한 번 더 처리할 위험이 있다.
프록시 → 서버 A: 주문 생성
서버 A: 생성 완료, 응답 전 연결 끊김
프록시 → 서버 B: 같은 요청 재시도
프록시가 A의 처리 여부를 알 수 없는 회색 구간이 생긴다. 메서드 이름만 보고 재시도 안전성을 정하지 말고 업무 작업이 멱등한지와 요청 본문을 다시 보낼 수 있는지를 확인해야 한다.
시간 초과는 앞단과 뒷단의 예산이 맞아야 한다
클라이언트, 프록시, 애플리케이션, 데이터베이스마다 시간 초과가 있다. 바깥쪽 제한이 3초인데 내부 작업이 30초까지 계속되면 클라이언트는 실패를 받았어도 서버 자원은 오래 사용된다.
데드라인(deadline: 전체 작업이 끝나야 하는 절대 시각이나 남은 시간 예산)을 내부 호출에 전달하면 남은 시간보다 긴 작업을 새로 시작하지 않게 할 수 있다. 단순히 각 단계에 3초씩 주면 여러 단계를 거치며 전체 시간이 늘어난다.
이해 확인 질문과 답변
리버스 프록시와 로드 밸런서는 완전히 다른 장비일까?
역할의 초점은 다르지만 하나의 소프트웨어나 서비스가 둘 다 수행할 수 있다. 요청을 대신 받고 전달하면서 동시에 여러 서버로 부하를 나누는 구성이 흔하다.
라운드 로빈이면 서버 부하가 항상 고르게 나뉠까?
아니다. 요청 수는 비슷해도 처리 시간이 다르고 서버 성능이 다르면 실제 CPU·메모리·연결 부하는 달라질 수 있다. 요청 성격에 맞는 기준과 가중치가 필요하다.
서버가 살아 있으면 readiness도 성공해야 할까?
그렇지 않다. 프로세스는 살아 있지만 초기화가 끝나지 않았거나 필수 의존성이 끊겨 새 요청을 받을 수 없을 수 있다. 재시작 여부와 트래픽 수신 여부를 따로 판단한다.
프록시가 실패 요청을 다른 서버로 재시도하면 항상 좋아질까?
아니다. 첫 서버가 실제 작업을 끝냈는지 모르는 상태에서 쓰기 요청을 다시 보내면 중복 결과가 생길 수 있다. 멱등성 보장과 재시도 가능한 경계를 확인해야 한다.
AI에게 이렇게 요청할 수 있다
클라이언트 요청이 리버스 프록시를 거쳐 서버 A, B, C로 전달되는 흐름을 보여 줘. 라운드 로빈과 최소 연결, readiness 실패로 서버가 제외되는 경우, 서버 A 응답 유실 뒤 프록시 재시도가 중복 작업을 만드는 경우를 비교해 줘.
앞단 서버는 요청을 고르게 나누는 데서 끝나지 않는다. 연결 경계를 나누고, 준비되지 않은 서버를 빼고, 시간 초과와 재시도가 업무 상태를 망치지 않도록 전달 규칙을 정한다.
'배움과 성장 > 네트워크·보안' 카테고리의 다른 글
| TLS는 공개된 네트워크에서 어떻게 안전한 연결을 만들까? 인증서와 세션 키 (0) | 2026.09.15 |
|---|---|
| 도메인 이름은 어떻게 서버 주소를 찾을까? DNS 질의와 캐시 (0) | 2026.09.14 |
| HTTP 요청은 어디서 시작해 어떤 응답으로 끝날까? 메서드와 상태 코드 (0) | 2026.09.06 |
| TCP는 빠진 데이터와 뒤바뀐 순서를 어떻게 다룰까? 순서 번호와 재전송 (0) | 2026.09.05 |
| Linux 네트워크 성능 분석 순서: TCP 큐·오프로드·qdisc 확인하기 (1) | 2026.06.03 |
댓글