처음에는 제한 알고리즘 하나만 고르면 끝날 것처럼 보입니다. 실제로는 여러 API 서버가 같은 마지막 토큰을 보지 않게 만들고, 저장소 장애 때 무엇을 허용할지까지 정해야 합니다.
시스템 디자인 운영자 · coreline-ai
3분 요약
개념 이해
면접 답변
실무 확장
진도 저장 ✓
⚡30초 핵심 요약
Token Bucket과 Sliding Window 중 무엇을 고를지보다 먼저 볼 것은 확인과 차감의 원자성입니다. 공유 Redis를 사용해도 두 동작을 나누면 여러 게이트웨이가 같은 마지막 토큰을 소비합니다. 보충·확인·차감·TTL을 한 Lua 실행으로 닫고, Redis 장애 때는 API 위험도별 fail-open과 fail-closed를 다르게 적용합니다.
예시 목표 처리량 (설계 가정)1,200,000 req/s
판정 지연 목표 (설계 가정)P99 < 10ms
일관성 우선순위중복 허용보다 과금 보호
01 · REQUIREMENTS
무엇을 제한할 것인가?
# 요구사항
공유 상태만 두면 끝나는 문제가 아닙니다. 사용자, API Key, IP, 조직, 엔드포인트별 정책을 나누고, 어떤 API는 초과 허용보다 차단이 안전한지까지 먼저 정합니다.
F1다중 정책
사용자·조직·API별 제한량과 윈도우를 설정합니다.
F2빠른 판정
정상 요청 경로에 추가되는 지연을 최소화합니다.
F3분산 공유
여러 서버가 동일한 사용량 상태를 확인합니다.
F4정확한 응답
429와 남은 횟수·재시도 시각을 전달합니다.
02 · HIGH-LEVEL DESIGN
고수준 아키텍처
# 아키텍처
요청은 Gateway에서 인증된 뒤 레이트 리미터로 전달됩니다. 정책과 사용량은 분리해 캐시하며, 판정 결과와 오류율은 관측 시스템으로 전송합니다.
분산 레이트 리미터 · 요청 판정 흐름 SVG DIAGRAM · 확대 가능
◉ClientWeb · Mobile · SDK
⇄API Gateway인증 · 정책 키 추출
⚡Rate Limiter정책 조회 · 토큰 차감 · 429 응답
Token BucketLua Script
▦Redis Cluster공유 카운터 · 정책 캐시
▤Application허용된 요청 처리
↗Observability허용률 · 거부율 · P99
설계 포인트 — Redis 장애 시 모든 요청을 차단할지(Fail Closed), 임시로 허용할지(Fail Open)는 API의 위험도와 비용 구조에 따라 정책별로 결정합니다.
DESIGN DECISION · 설계 판단
토큰 확인과 차감 사이의 경쟁 조건을 어디에서 닫을 것인가?
예시 목표 처리량1,200,000 req/s
설계 가정
판정 지연 목표P99 < 10ms
설계 가정
배포 형태다중 API 서버
설계 가정
최종 선택
Redis Token Bucket + Lua 단일 판정 + API 등급별 장애 정책
보충량 계산·잔여 토큰 확인·차감·TTL 갱신을 한 Lua 실행으로 끝냅니다. Redis 장애 때 결제·관리 API는 fail-closed, 공개 조회는 제한된 emergency bucket을 사용합니다.
선택 이유
여러 게이트웨이가 같은 마지막 토큰을 동시에 보고 초과 허용하는 경쟁 조건을 막습니다.
정책 버전과 판정 결과를 함께 남겨 429 감소와 보호 대상 부하를 구분할 수 있습니다.
API 위험도에 따라 가용성과 보호 우선순위를 다르게 운영할 수 있습니다.
포기한 대안
GET 뒤 DECR를 분리한 공유 카운터
여러 요청이 같은 잔여 토큰을 읽어 모두 허용될 수 있습니다. 공유 저장소를 쓴다는 사실만으로 원자성이 생기지 않습니다.
감수한 단점
정상 요청 경로가 Redis 지연과 장애에 의존합니다.
유명 조직 키는 hot key가 되어 단일 샤드의 처리량을 제한할 수 있습니다.
리전별 emergency bucket은 가용성을 얻는 대신 짧은 전역 한도 초과를 허용합니다.
03 · REQUEST FLOW
요청은 어떻게 판정되는가?
# 처리 흐름
1제한 키 생성
userId + endpoint + policyVersion으로 키를 만듭니다.
2정책 조회
로컬 캐시에서 용량과 보충률을 확인합니다.
3원자적 차감
Lua Script로 토큰 확인과 감소를 한 번에 수행합니다.
4응답·관측
허용 또는 429를 반환하고 메트릭을 기록합니다.
04 · ALGORITHM
알고리즘 비교
# 트레이드오프
일반 API라면 Token Bucket이 현실적인 기본안입니다. 다만 emergency bucket과 리전별 예산을 운영해야 하고 잠시 전역 한도가 어긋날 수 있습니다. 그 단점을 감수하더라도 중앙 장애 때 모든 요청을 한꺼번에 허용하거나 차단하는 것보다 영향 범위를 설명하기 쉽습니다.
“전 세계 사용자에게 하나의 전역 제한량을 정확히 적용해야 한다면 지연 시간과 일관성을 어떻게 조정하시겠습니까?”
답변 구조 보기 4단계
제한 대상과 과금·보안 위험도를 먼저 분리한다.
키 설계, 알고리즘, 공유 저장소의 원자성 경계를 설명한다.
Redis 장애 때 API별 fail-open/fail-closed를 결정한다.
Hot key·리전 단절·업무 멱등성까지 운영 지표와 함께 답한다. 이번 선택: 일반 API는 공유 Redis token bucket과 Lua 원자 차감을 사용한다. 깨지는 신호: 저장소 p99, hot key 비율, 허용 초과율이 함께 상승한다. 다음 검증: 프로모션 버스트와 Redis timeout을 주입해 API 등급별 fail-open/fail-closed가 약속대로 갈리는지 확인한다.