52장. API Gateway — REST API vs HTTP API
이 장에서 말하고자 하는 것
ALB까지 깔면 외부 트래픽이 ECS로 들어오는 길은 만들어진다.
그런데 운영하다 보면 다음이 필요해진다.
- 사용자 인증 (JWT · OAuth · API Key)
- 사용량 제한 (Rate limit · Quota)
- 요청/응답 변환
- 버전 관리
- 서드파티 API와의 결합
이걸 ALB로 다 풀면 애플리케이션이 무거워진다.
이 문제를 한 단계 위에서 다루는 도구가
Amazon API Gateway
다.
1. API Gateway 위치
[사용자]
↓
[CloudFront]
↓
[API Gateway] ← 여기, 인증·제한·변환
↓
[ALB]
↓
[ECS]
CloudFront와 ALB 사이에서 API 진입점 역할을 한다.
2. REST API vs HTTP API
| 항목 | REST API | HTTP API |
|---|---|---|
| 출시 | 오래됨 | 신형 |
| 가격 | 비쌈 | 1/3 ~ 2/3 |
| 기능 | 풍부 (사용량 계획, API Key, Mock) | 핵심만 |
| 지연 | 큼 | 작음 |
| 권장 | 레거시 | 새 프로젝트 |
새로 시작한다면 HTTP API 가 표준
사용량 계획 · 복잡한 변환이 정말 필요할 때만 REST API
3. API Gateway가 해주는 것
인증
- JWT (Cognito · 외부 IdP)
- Lambda Authorizer (커스텀 검증)
- IAM 서명 (내부 호출)
제한
- Rate limit (초당 N건)
- Burst (순간 허용량)
변환
- 요청 헤더/바디 변환
- 응답 변환
통합 대상
- HTTP (ALB · 외부 URL)
- Lambda
- AWS 서비스 직접 (DynamoDB · SQS 등)
- VPC Link (프라이빗 ALB / NLB)
4. VPC Link — API Gateway가 내부 ALB로 가는 길
API Gateway는 기본적으로 인터넷 쪽이다.
[API Gateway] ← 인터넷
↓ VPC Link
[Private ALB] ← VPC 안
↓
[ECS]
ALB를 인터넷에 노출하지 않고도 API Gateway로 받아 내부로 전달할 수 있다.
5. ALB가 있는데 API Gateway도 필요한가
- ALB는 L7 라우팅 + 헬스 체크 + 트래픽 분배가 강함
- API Gateway는 인증 · 제한 · 변환이 강함
순수 내부용 ALB만으로 충분 → API Gateway 없음
공개 API · 외부 파트너 · 인증 필요 → API Gateway
대부분의 공개 SaaS는 둘 다 쓴다.
6. 우리 서비스에서
[CloudFront]
├─ /static/* → S3
└─ /api/*
↓
[API Gateway]
├─ JWT 인증
├─ Rate limit
└─ VPC Link
↓
[Private ALB]
├─ /api/orders/* → ECS "orders"
├─ /api/users/* → ECS "users"
└─ /api/payments/* → ECS "payments"
7. 직접 확인해보기 — CLI
aws apigatewayv2 create-api \
--name orders-api \
--protocol-type HTTP
aws apigatewayv2 create-vpc-link \
--name to-alb \
--subnet-ids subnet-x subnet-y \
--security-group-ids sg-z
aws apigatewayv2 create-route \
--api-id <api-id> \
--route-key "GET /api/orders" \
--target "integrations/<integration-id>"
8. 코드로는 이렇게 생겼다 — Terraform
resource "aws_apigatewayv2_api" "main" {
name = "msa-api"
protocol_type = "HTTP"
}
resource "aws_apigatewayv2_vpc_link" "alb" {
name = "to-alb"
security_group_ids = [aws_security_group.apigw.id]
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
}
resource "aws_apigatewayv2_integration" "alb" {
api_id = aws_apigatewayv2_api.main.id
integration_type = "HTTP_PROXY"
integration_uri = aws_lb_listener.https.arn
connection_type = "VPC_LINK"
connection_id = aws_apigatewayv2_vpc_link.alb.id
integration_method = "ANY"
}
resource "aws_apigatewayv2_route" "proxy" {
api_id = aws_apigatewayv2_api.main.id
route_key = "ANY /api/{proxy+}"
target = "integrations/${aws_apigatewayv2_integration.alb.id}"
}
resource "aws_apigatewayv2_stage" "prod" {
api_id = aws_apigatewayv2_api.main.id
name = "$default"
auto_deploy = true
}
이 모양이 “공개 → APIGW → VPC Link → 프라이빗 ALB” 의 기본형이다.
9. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. 새 프로젝트에 REST API를 그냥 쓴다
비용과 지연만 늘어난다. 신규는 HTTP API.
안티패턴 2. ALB가 인터넷에 노출돼 있는데 API Gateway도 둔다
API Gateway 우회로가 열린다. ALB는 프라이빗으로 옮기고 VPC Link로 받는다.
안티패턴 3. API Gateway 안에 비즈니스 로직을 박는다
복잡한 변환을 VTL에 박으면 유지보수가 어렵다.
비즈니스 로직은 애플리케이션, API Gateway는 얇은 진입점
안티패턴 4. Rate limit을 안 건다
악의적 트래픽 한 번에 다운스트림이 무너진다.
10. 한 줄로 정리
API Gateway는 인증 · 제한 · 변환을 다루는 공개 API의 진입점이며,
VPC Link로 프라이빗 ALB를 안전하게 노출한다
11. 이 장의 핵심 정리
- API Gateway는 ALB 앞에서 인증 · 제한 · 변환을 책임진다.
- 새 프로젝트는 HTTP API가 기본 선택지다.
- VPC Link로 프라이빗 ALB를 노출할 수 있다.
- ALB는 내부, API Gateway는 외부 — 역할을 분리한다.
- Rate limit은 거의 항상 켠다.