L4 vs L7 로드밸런서 — 패킷을 어디까지 여는가
앞단에 로드밸런서를 하나 둘 때 AWS 면 NLB 냐 ALB 냐를 고르고, 서버를 직접 두고 쓰는 환경이면 L4 스위치냐 nginx 냐를 고르게 됩니다. 어느 쪽이든 L4 냐 L7 이냐를 먼저 정하는데, 이걸 제품 종류로 외워 두면 처음 몇 번은 넘어가다가 나중에 막힙니다.
TLS 를 끊지 말고 그대로 통과시켜야 한다거나, 백엔드 서버 로그에 클라이언트 IP 가 그대로 찍혀야 한다는 요구가 들어왔을 때 왜 한쪽은 되고 한쪽은 안 되는지가 안 나옵니다. 제품 이름으로 외워 둔 지식은 NLB 가 L4 고 ALB 가 L7 이라는 데까지만 답해 주고, 그 둘이 왜 그렇게 갈리는지는 답해 주지 않습니다.
둘을 가르는 건 결정을 내리려고 패킷을 얼마나 열어 보느냐 하나입니다.
얼마나 열어보느냐로 갈리는 계층
L4 는 IP 와 포트까지만 보고 그 안의 HTTP 헤더나 URL 은 안 열지만, L7 은 그 위로 HTTP 메서드·Host·경로·쿠키까지 열어서 봅니다.
결정적 차이 — L7의 연결 종료·재수립
L4 는 들어온 TCP 연결을 그대로 백엔드로 넘깁니다(포워딩/NAT). 클라이언트와 서버 사이의 연결이 끊기지 않고 그대로 이어집니다. L7 은 클라이언트의 TCP 연결을 자기가 종료하고 백엔드로 새 연결을 맺으니 중간에 프록시가 하나 들어가는 구조입니다.
그래서 TLS passthrough 는 L4 만 되고, L7 은 라우팅하려면 HTTP 를 봐야 하고 HTTPS 면 그 내용을 보려고 반드시 TLS 를 종료해야 하니 암호화된 채로 뒤로 넘기는 건 구조적으로 불가능합니다.
L4 는 연결을 그대로 넘기니 서버가 클라이언트의 실제 IP 를 보고, 여기서 클라이언트 IP 가
보이는 방식이 갈립니다. L7 은 연결을 새로 맺으니 서버가 보는 소스 IP 가 로드밸런서 IP 가 되고, 원래 IP 는
X-Forwarded-For 헤더에 실려 옵니다.
다만 NLB 는 타겟 타입이 IP 이고 프로토콜이 TCP·TLS 면 클라이언트 IP 보존이 기본으로 꺼져
있습니다. EKS 에서 IP 타겟으로 붙이는 흔한 구성이 여기 해당하니, preserve_client_ip.enabled 를
따로 켜야 합니다.
NLB 와 ALB — 열어 보는 범위의 차이
| NLB (L4) | ALB (L7) | |
|---|---|---|
| 보는 것 | IP·포트·프로토콜 | + HTTP Host·경로·헤더 |
| TLS | passthrough 가능 | 반드시 종료 |
| 클라이언트 IP | 서버가 직접 확인 (IP 타겟은 보존 옵션 필요) | X-Forwarded-For |
| 라우팅 | 4-튜플 기반 | Host·경로·헤더 기반 |
| 속도 | 극저지연(거의 안 엶) | 파싱·복호화만큼 느림 |
ALB 뒤의 nginx 에서 진짜 클라이언트 IP 를 로그에 남기려면 두 줄이 같이 있어야 합니다.
set_real_ip_from 에 ALB 가 있는 서브넷 대역을 적고, real_ip_header 를 X-Forwarded-For 로
잡습니다. 신뢰할 대역을 안 적으면 헤더를 읽지 않아서 $remote_addr 에 ALB 내부 IP 만 찍힙니다.
그래서 무엇을 고르나
DB 커넥션이나 고정 IP 화이트리스트, mTLS passthrough 처럼 내용을 안 봐도 되고 원본 IP 와 암호화를 그대로 보존해야 하는 자리는 L4(NLB)입니다. Host 나 경로로 분기하거나 WAF 를 붙여야 하면 요청 내용을 봐야 하니 L7(ALB)입니다.
L7 을 고른 순간 연결을 끊고 복호화하는 비용, 그리고 passthrough 불가라는 제약을 같이 받습니다.
댓글 0