어제 배운 내용을 팀원에게 공유했다.

MSA 인프라를 설계하다 보면 엣지 레이어에 놓을 수 있는 후보가 세 개 나온다. (어제는 ALB, Nginx만 고려해봤지만, API Gateway도 올 수 있다는 것을 회의중에 알게 되었다.)
ALB, Nginx, API Gateway. 셋 다 "퍼블릭에서 들어온 요청을 프라이빗 영역의 서비스로 넘겨주는" 라우팅 역할을 할 수 있다. 그래서 헷갈린다.

"어차피 다 되는데 뭘 써야 하지?"
이 글은 그 결정을 트레이드오프로 풀어낸 기록이다.
결론부터 말하면 현재 학습 프로젝트 상황에서는 ALB 하나만 두는 게 합리적이고, 그 이유를 하나씩 정리했다.
AWS가 제공하는 관리형 L7 로드밸런서.
L7이란 OSI 7계층 모델의 최상위, 즉 HTTP 계층을 본다는 뜻이다. "/api/users는 유저 서비스로, /api/orders는 주문 서비스로" 같은 URL 기반 라우팅이 가능하다는 얘기다.
본질적인 역할은 "여러 타겟에 트래픽을 분산하고, 죽은 놈은 빼고, TLS를 종료"하는 것이다. AWS가 알아서 관리해주기 때문에 사용자는 설정만 하면 된다.
범용 리버스 프록시 소프트웨어. 설치하고 설정 파일만 쓰면 어디서든 돌아간다. 유연성이 가장 크다. URL 리라이트, 캐싱, 정적 파일 서빙, 복잡한 헤더 조작까지 거의 뭐든 가능하다. 대신 내가 직접 서버에 올리고, 죽으면 복구하고, 스케일링까지 직접 해야 한다.
MSA 맥락의 애플리케이션 레벨 게이트웨이. 앞의 두 개와 결이 다르다. JWT 토큰을 검증하고, 서비스 디스커버리랑 연동하고, 여러 MSA 응답을 합쳐서 클라이언트에 돌려주는 등 비즈니스를 이해하는 엣지다.
ALB나 Nginx는 "이 요청의 JWT userId가 뭔지, 이 사용자가 분당 몇 번 호출했는지" 같은 건 모른다. API Gateway는 안다.
ALB와 Nginx 두 가지만 비교한 내용은 어제 정리해보았다.
엣지 레이어(Edge Layer) 설계 - ALB vs Nginx
API Gateway도 올 수 있다는 것을 회의중에 알게 되자
"API Gateway 하나로 퍼블릭 노출도 하고 MSA 라우팅도 하면 되지 않나?"의문이 들었다.
실제로 된다. 다만 몇 가지 현실적인 문제가 생긴다.
HA(High Availability, 고가용성)는 "서버 한 대 죽어도 서비스 안 멈추게" 만드는 것이다. 보통 여러 대 띄우고 앞에 로드밸런서를 둔다.
API Gateway를 여러 대 띄우면 클라이언트가 어느 인스턴스로 요청을 보낼지 결정해야 한다. DNS 라운드로빈으로 돌리자니 헬스체크가 없어서 죽은 놈한테도 요청이 간다. 결국 앞에 로드밸런서 하나가 필요해진다. AWS 환경에선 그게 ALB다.
즉 "API Gateway만 쓰자" → HA 하려니 앞단이 필요 → ALB가 다시 등장.
API Gateway를 직접 인터넷에 노출하면 애플리케이션이 다음을 전부 떠안는다.
DDoS 방어: DDoS는 수많은 좀비 컴퓨터가 동시에 요청을 퍼부어 서버를 다운시키는 공격이다. AWS는 Shield Standard라는 것을 ALB에 자동으로 무료 적용해준다. SYN flood 같은 네트워크 계층 공격을 ALB 단에서 걸러서 뒷단까지 도달하지 않게 한다. 반면 Spring Cloud Gateway를 EC2에 직접 띄워서 퍼블릭으로 열면 Shield의 보호를 못 받고, 커넥션 폭주가 애플리케이션까지 그대로 도달한다. Spring은 이런 공격에 약해서 금방 뻗는다.
TLS 인증서 관리: HTTPS를 쓰려면 TLS 인증서가 필요하고, 이 인증서는 유효기간이 있어서(보통 3개월~1년) 주기적으로 갱신해야 한다. 까먹으면 "이 사이트는 안전하지 않습니다" 경고가 뜨면서 장애가 난다. AWS는 ACM(AWS Certificate Manager)으로 인증서를 무료 발급해주고 자동 갱신까지 해준다. 단, ACM 인증서는 ALB 같은 AWS 리소스에만 붙일 수 있다. EC2에 직접 띄운 Spring Cloud Gateway에는 못 쓰니 Let's Encrypt를 직접 쓰고 certbot 설정하고 cron 돌리고 갱신 실패 모니터링까지 직접 해야 한다.
TLS 종료: HTTPS 요청을 엣지에서 복호화해서 내부망엔 평문 HTTP로 넘기는 것을 "TLS 종료"라고 한다. ALB가 이걸 대신 해주면 내부 서비스마다 인증서를 관리할 필요가 없다.
"그럼 API Gateway 하나가 다 하는 게 아니라, 퍼블릭 입구 역할을 하는 API Gateway를 앞에 두고, 그 뒤에 JWT 검증과 MSA 라우팅을 하는 API Gateway를 따로 두면 되지 않나?" 하는 구조도 생각해볼 수 있다.
퍼블릭 | API Gateway (입구·분산) → || 내부 API Gateway (JWT·라우팅) → MSA
이 구조면 JWT 로직을 바꿔도 뒷단만 배포하면 되니 퍼블릭 엔드포인트는 안 흔들린다. 합리적인 시도처럼 보인다.
문제는 앞단 API Gateway가 결국 ALB 역할을 소프트웨어로 다시 만드는 꼴이라는 점이다. 앞단이 하는 일을 뜯어보면 "퍼블릭 트래픽 받기, TLS 종료, 뒷단 인스턴스로 분산, 헬스체크"인데, 이건 정확히 ALB가 관리형으로 공짜에 해주는 일이다. 그걸 Spring Cloud Gateway나 Kong 같은 애플리케이션으로 직접 올리면 문제 1과 문제 2가 그대로 반복된다.
덤으로 네트워크 홉(hop, 한 단계 거치는 것)도 하나 늘어난다. 앞단 Gateway → 뒷단 Gateway → MSA는 ALB → API Gateway → MSA보다 응답 지연이 크고 장애 지점이 하나 더 많다.
즉 "API Gateway를 두 층으로 쪼개도 앞단에서 ALB의 문제가 그대로 반복된다." 그 앞단을 ALB로 바꾸는 순간 위 부담이 전부 사라지고, 뒷단 API Gateway는 JWT와 MSA 라우팅 같은 비즈니스 영역에만 집중할 수 있다. 관심사 분리가 자연스럽게 맞춰지는 것이다.
ALB가 앞에 있으면 "502 에러가 뜨면 Gateway 문제, ALB가 안 뜨면 인프라 문제"로 구분이 깔끔하다. API Gateway가 다 하면 장애가 났을 때 인프라 문제인지 애플리케이션 버그인지 섞여서 원인 파악이 오래 걸린다.
Nginx도 위의 일들을 할 수 있다. 리버스 프록시, TLS 종료, 라우팅, 심지어 Lua 스크립트를 붙이면 JWT 검증 같은 것도 가능하다. 그런데 AWS 환경에선 Nginx를 굳이 쓸 이유가 별로 없다. ALB가 관리형으로 해주는 일을 Nginx로 직접 하는 건 중복 노동이기 때문이다.
Nginx가 정당화되는 경우는 이렇다.
학습 프로젝트에선 이런 요구사항이 없으니 Nginx를 미리 넣을 필요가 없다. "나중에 ALB로 안 되는 X가 필요해졌다"는 순간이 오면 그때 추가하면 된다.
Route53 → ALB (퍼블릭) → API Gateway (프라이빗) → 각 MSA
각자의 역할을 정리하면:
ALB가 맡는 것 — 인프라 레벨 엣지
API Gateway가 맡는 것 — 애플리케이션 레벨 엣지
Nginx는 빠진다
ALB와 역할이 겹치고, 학습 프로젝트에 직접 운영 부담을 질 이유가 없다.
핵심은 AWS 환경에서 ALB는 사실상 "공짜 HA 분산기"라는 점이다. AWS가 관리형으로 HA, TLS 자동 갱신, DDoS 방어를 다 해주기 때문에 안 쓸 이유가 거의 없다.
반면 API Gateway 하나로 다 하려고 하면, HA 구성, 인증서 관리, DDoS 방어, 무중단 배포를 전부 직접 해결해야 한다. MSA를 공부하려고 만든 프로젝트가 인프라 운영 프로젝트로 변질되는 순간이다.
학습의 초점을 "MSA 게이트웨이의 역할(JWT 검증, 서비스 디스커버리, 요청 집계)"에 두고 싶다면, 그 외의 인프라 관심사는 ALB에게 맡기고 손 떼는 게 맞다. 관심사 분리는 이론상 "잘 쓰면 되는 문제"지만, 실제로는 레이어를 나눠두는 것 자체가 잘 쓸 수 있게 해주는 장치다.
Nginx는 나중에 필요해지면 추가하고, 지금은 ALB → API Gateway 2계층으로 간다.
API 구현 중요도를 상, 중, 하로 나누어서 상 만 구현
MVP 범위에서 벗어나는 부분은 명세에서 제외하기로 했다.
