| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- JavaScript
- architecture
- HTTP
- Performance
- backend
- API
- Infra
- database
- SRE
- 버전관리
- CI
- Git
- DevOps
- observability
- react
- CSS
- Kubernetes
- Microservices
- web
- aws
- Operations
- NextJS
- version-control
- 성능
- reliability
- Debugging
- Ops
- auth
- frontend
- Security
- Today
- Total
고민보단 실천을
레이트리밋 응답 설계: 429 + RFC 9331 RateLimit 헤더로 클라이언트 재시도 폭주 막기 본문
레이트리밋 응답 설계: 429 + RFC 9331 RateLimit 헤더로 클라이언트 재시도 폭주 막기
레이트리밋은 '막는 것'이 아니라 '안전하게 실패시키는 것'입니다.
429 응답에 RateLimit 헤더(RFC 9331)와 Retry-After를 어떻게 넣어야 클라이언트 재시도 폭주를 줄일 수 있는지 정리합니다.
이 글의 목표는 '개념 정리'보다, "어떤 기준으로 결정할지"와 "어떻게 운영에서 사고를 줄일지"를 남기는 것입니다.
왜 이게 어려운가(운영 관점)
API/HTTP 영역은 '작은 정책'이 전체 사용자 경험과 운영 비용을 바꿉니다. 그래서 실무에서는 구현보다도 기준(정책)과 검증 루프가 중요합니다.
특히 프록시/CDN/게이트웨이가 있는 환경에서는 서버 코드만 보면 원인을 놓치기 쉽습니다. 레이어를 같이 정리해두면 같은 장애를 반복하지 않게 됩니다.
실전 내용(바로 적용)
레이트리밋은 '막는 것'이 아니라 '안전하게 실패시키는 것'입니다.
429 응답에 RateLimit 헤더(RFC 9331)와 Retry-After를 어떻게 넣어야 클라이언트 재시도 폭주를 줄일 수 있는지 정리합니다.
핵심 요약(결론부터)
- 기준(정책)을 먼저 정하고, 구현/도구는 그 다음에 선택한다
- 실패/예외/회귀를 운영 체크리스트로 막는다
- 공식 문서를 최종 근거로 삼고, 팀 문서로 재가공한다
왜 헤더 설계가 중요한가
서버가 429를 보내도 클라이언트가 무한 재시도하면 장애가 증폭된다
표준 헤더를 쓰면 클라이언트/SDK가 자동으로 해석하기 쉬워진다
실무 기본값(추천)
- 429는 '일시적 제한'에만 사용하고, 영구 거부는 403 등으로 분리
- Retry-After는 초 단위로 명확히
- RateLimit은 limit/remaining/reset을 일관되게
응답 예시(헤더)
HTTP/1.1 429 Too Many Requests
Retry-After: 5
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 1700000000운영 체크리스트(바로 적용)
- 클라이언트 재시도 정책(backoff+jitter+상한)을 문서화한다
- 사용자/토큰/IP 기준을 혼합해 우회 난이도를 올린다
- 레이트리밋 초과율을 지표로 보고, 임계치에서 알람을 건다
FAQ
Q. 429면 클라이언트가 자동으로 기다리나요?
A. 자동은 아닙니다. 하지만 Retry-After/RateLimit 헤더를 표준으로 제공하면 클라이언트 구현이 쉬워지고, SDK도 이를 활용할 수 있습니다.
마무리: 다음 액션
- 팀의 기본값(정책)을 1페이지로 문서화한다
- 대표 시나리오 1개를 코드/설정 예시로 고정한다
- 배포 전후 지표(p95/p99, 오류율)를 비교해 효과를 확인한다
자주 하는 실수(사고 패턴)
- 결정 기준 없이 팀원 취향으로 기술을 고른다
- 문서(스키마)와 구현이 어긋난 상태를 장기간 방치한다
- 재시도/타임아웃을 '늘리기'만 하고 예산/정렬을 안 맞춘다
- 장애 시나리오(429/timeout/partial failure)를 테스트에 넣지 않는다
적용 순서(추천)
- 1) 바꾸려는 것(성능/보안/호환성/운영 단순화)을 한 문장으로 정의한다
- 2) 기본값과 예외를 먼저 정하고, 예외는 만료일/사유/소유자를 남긴다
- 3) 대표 시나리오(요청/응답 예시)를 만들어 계약으로 고정한다
- 4) 지표(p95/p99, 오류율, 재시도율)로 배포 전후를 비교한다
- 5) CI/PR에서 자동 검증(린트/스키마 diff/계약 테스트)을 걸어 회귀를 막는다
검증/회귀 방지
- 배포 전후 지표(p95/p99, 4xx/5xx, 재시도율)를 동일 조건으로 비교
- 프록시/CDN/게이트웨이 설정 변경 이력을 남기고, 롤백 플랜을 준비
- 대표 시나리오를 e2e 테스트로 고정(문서가 아니라 테스트가 계약이 되게)
팀 합의 템플릿(복붙용)
# 팀 합의 템플릿(복붙용)
목표: (예) 구버전 클라이언트 유지하면서 응답 스키마 변경
기본값: (예) /v1 경로 버전 사용
예외: (예) 내부 API는 헤더 버전 허용(게이트웨이 필수)
대표 시나리오: (요청/응답 예시 첨부)
모니터링: (오류율/지연/트래픽) 대시보드 링크
EOL/변경 정책: (날짜/공지 채널/롤백 규칙)FAQ
Q. 429면 클라이언트가 자동으로 기다리나요?
A. 자동은 아닙니다. 하지만 Retry-After/RateLimit 헤더를 표준으로 제공하면 클라이언트 구현이 쉬워지고, SDK도 이를 활용할 수 있습니다.
참고/출처
버전/환경에 따라 동작이 달라질 수 있으니, 최종 기준은 공식 문서를 확인합니다.
