레이트 리미팅 (Rate Limiting)
목차
- 왜 이 주제를 묻는가
- 레이트 리미팅이란
- 기준 단위와 정책 모델
- Burst와 Sustained Limit
- 429와 Retry-After
- 대표 알고리즘 비교
- 분산 환경에서의 상태 저장
- 어디에서 집행할까
- Quota, Abuse Protection, Backpressure의 차이
- 자주 하는 실수
- 면접 포인트
- 참고 자료
왜 이 주제를 묻는가
백엔드 면접에서 레이트 리미팅은
“초당 N번 막습니다”로 끝나는 기능 질문이 아닙니다.
보통은 다음을 같이 확인합니다.
- 무엇을 보호하는가: 백엔드, 특정 사용자 그룹, 외부 파트너 API, 비용이 큰 연산
- 무엇을 기준으로 제한하는가: IP, 사용자, 토큰, tenant, API key, 엔드포인트
- 초과 시 어떻게 반응하는가: 즉시 거절, 지연, 큐잉, 강한 차단
- 어디에서 집행하는가: Edge, 애플리케이션 서비스, 비동기 워커
이 문서는 시스템 설계 관점에서 어떤 단위로 제한하고, 어떤 알고리즘과 저장소를 택할지, 그 대가가 무엇인지를 설명합니다.
API Gateway 설정이나 Redis 명령 수준의 운영 상세는 API Gateway와 Edge 패턴 (API Gateway and Edge Patterns), 캐싱 (Caching) 문서를 함께 보면 더 직접적입니다.
레이트 리미팅이란
레이트 리미팅(Rate Limiting) 은 일정 시간 동안 허용할 요청 수나 작업 수를 제한하는 정책입니다.
핵심 목적은 보통 다음 중 하나입니다.
- 남용 방지: 브루트포스, 스크래핑, 비정상 트래픽 차단
- 백엔드 보호: 특정 API나 저장소가 과부하로 무너지지 않게 완충
- 공정성 확보: 일부 사용자나 tenant가 전체 자원을 독점하지 못하게 제어
- 비용 관리: 외부 API 호출, AI 추론, 대용량 조회처럼 비싼 작업 사용량 제한
좋은 답변은 “트래픽을 막습니다”보다
무엇을 보호하려고 어떤 속도를 허용하는지를 함께 설명하는 답변입니다.
기준 단위와 정책 모델
레이트 리미팅은 “몇 번까지 허용할까”보다 먼저 무엇을 하나의 주체로 볼까를 정해야 합니다.
대표 기준은 다음과 같습니다.
| 기준 단위 | 잘 맞는 경우 | 주의점 |
|---|---|---|
| IP | 비로그인 공개 API, 1차 방어 | NAT, 프록시, 모바일망에서는 여러 사용자가 같은 IP를 공유할 수 있음 |
| 사용자 ID | 로그인 사용자 기반 API | 인증 이전 단계에는 적용하기 어려움 |
| API Key / 토큰 | 외부 파트너, 서버 간 호출 | 키 공유 시 실제 사용자 분리가 어려움 |
| Tenant | SaaS 멀티 테넌시 | tenant 내부 공정성은 따로 설계해야 할 수 있음 |
| 엔드포인트 | 비싼 API만 별도 보호 | 전체 사용자 공정성과는 다른 문제 |
실무에서는 하나만 쓰기보다 보통 여러 기준을 겹쳐서 봅니다.
- 로그인 이전에는 IP 기준으로 1차 제한
- 로그인 이후에는 사용자나 토큰 기준으로 세밀한 제한
- 큰 고객이 있는 SaaS라면 tenant quota를 별도로 둠
- 비용이 큰 엔드포인트는 더 강한 제한을 둠
즉, 레이트 리미팅은 단일 숫자보다 정체성 모델과 보호 대상 모델이 먼저입니다.
Burst와 Sustained Limit
레이트 리미팅을 설계할 때 자주 놓치는 점은
순간적인 폭주를 허용할 것인지, 장기 평균 사용량을 통제할 것인지가 다르다는 점입니다.
- Burst Limit: 짧은 시간 동안 몰리는 요청을 얼마나 허용할지
- Sustained Limit: 더 긴 시간 동안 평균적으로 어느 정도 사용량을 허용할지
예를 들면:
- 초당 10건까지는 허용하지만 1분 동안은 최대 300건
- 평소에는 초당 5건이지만, 짧게는 20건까지 burst 허용
- 로그인 API는 burst를 강하게 제한하고, 일반 조회 API는 조금 더 유연하게 허용
이 차이를 말하지 않으면
“초당 N건” 같은 숫자가 실제 사용자 경험이나 백엔드 보호 목표와 잘 안 맞을 수 있습니다.
좋은 답변은 짧은 피크는 흡수하되, 지속적 남용은 제한한다는 식으로 정리하면 됩니다.
429와 Retry-After
레이트 리밋을 넘겼을 때는 보통 HTTP 429 Too Many Requests를 사용합니다.1
여기서 중요한 것은 상태 코드만이 아닙니다.
- 언제
429를 반환하는가 - 클라이언트가 얼마나 기다렸다가 다시 시도해야 하는가
Retry-After헤더를 줄 것인가- 단순 거절인지, 점진적 감속인지
Retry-After는 HTTP에서 재시도 시점을 알려 주는 표준 헤더입니다.2
좋은 답변은 “429를 줍니다”보다
클라이언트가 복구 행동을 할 수 있게 계약을 만든다는 쪽입니다.
예를 들어:
- 공개 API는
429와Retry-After를 함께 줘서 재시도 시점을 안내 - 내부 서비스 호출은 공통 SDK가 이를 해석해 backoff
- 로그인/OTP 같은 보안 경계는 더 보수적으로 거절
대표 알고리즘 비교
레이트 리미팅 알고리즘은 완벽한 정답이 있는 것이 아니라, 정확도, 메모리 비용, 구현 난이도를 어떻게 바꿀지의 문제입니다.
| 알고리즘 | 장점 | 주의점 | 잘 맞는 경우 |
|---|---|---|---|
| Fixed Window | 단순하고 구현이 쉬움 | 윈도우 경계에서 요청이 몰리면 실제 허용량이 튈 수 있음 | 단순 API 보호, 메모리 효율 우선 |
| Sliding Window | 체감상 더 공정한 제한 가능 | 구현과 저장 비용이 더 복잡해짐 | 사용자 경험과 정확도가 중요할 때 |
| Token Bucket | burst 허용과 평균 속도 제어를 함께 다루기 좋음 | 토큰 충전 속도와 버킷 크기 튜닝이 필요 | 공개 API, 트래픽 완충 |
| Leaky Bucket | 일정한 배출 속도를 만들기 좋음 | 큐잉/배출 모델 이해가 필요 | 트래픽 shaping, 다운스트림 보호 |
면접에서는 보통 다음 정도로 정리하면 충분합니다.
- Fixed Window: 가장 단순하지만 경계 효과가 큼
- Sliding Window: 더 공정하지만 비용이 더 듦
- Token Bucket: burst 허용과 평균 제한을 함께 설명하기 좋음
Sliding Window도 구현 방식에 따라 결이 다릅니다.
- Sliding Window Log: 요청 시각을 개별 기록해 더 정확하지만 저장 비용이 큼
- Sliding Window Counter: 시간 구간별 카운터를 이용해 더 가볍지만 근사치가 될 수 있음
즉, 좋은 답변은 알고리즘 이름을 나열하는 것이 아니라
왜 이 워크로드에서 그 알고리즘을 택하는지를 말하는 답변입니다.
분산 환경에서의 상태 저장
인스턴스가 여러 대인 시스템에서는 레이트 리미팅 상태를 어디에 둘지가 중요합니다.
대표 선택지는 다음과 같습니다.
- 프로세스 로컬 메모리: 가장 빠르지만 인스턴스별로 상태가 갈라짐
- 공유 캐시/Redis: 여러 인스턴스에서 일관된 카운터를 보기 쉬움
- API Gateway / Load Balancer 내장 기능: 공통 정책을 입구에서 일관되게 적용하기 좋음
Redis는 카운터와 만료 시간을 다루기 쉬워 레이트 리미팅에 자주 쓰입니다. Redis 문서도 INCR와 EXPIRE를 이용한 rate limiter 패턴을 소개합니다.3
다만 분산 환경에서는 다음을 같이 봐야 합니다.
- 원자성: 카운터 증가와 TTL 설정이 함께 보장되는가
- 키 설계:
user_id:endpoint:window같은 기준 단위가 명확한가 - 시간 기준: 여러 인스턴스에서 윈도우 기준이 지나치게 어긋나지 않는가
- 장애 정책: 제한 저장소가 느리거나 죽었을 때 fail-open 할지 fail-closed 할지
멀티 리전이나 전역 서비스에서는 더 현실적인 절충도 필요합니다.
- 모든 리전에서 정확한 전역 카운터를 강하게 맞추려면 지연과 복잡도가 커질 수 있음
- 그래서 실제로는 리전별 제한 + 전역 근사 제한을 조합하거나, 강한 정확도보다 백엔드 보호를 우선하는 경우가 많음
예를 들어 로그인 방어는 fail-open보다 fail-closed가 자연스러울 수 있고,
일반 조회 API는 제한 저장소 장애 때문에 전체 서비스가 멈추지 않게 fail-open이 더 현실적일 수 있습니다.
즉, 레이트 리밋 저장소는 단순 카운터 DB가 아니라 정책 정확도와 장애 전파를 함께 좌우하는 구성 요소입니다.
어디에서 집행할까
레이트 리미팅은 위치에 따라 의미가 달라집니다.
| 집행 위치 | 장점 | 주의점 |
|---|---|---|
| Edge / Gateway | 공통 정책을 입구에서 일관되게 적용 가능 | 도메인 의미를 잘 모르면 과하거나 부족한 제한이 될 수 있음 |
| 서비스 내부 | 사용자 상태, 비즈니스 비용, tenant 등 문맥을 잘 앎 | 서비스마다 구현이 흩어질 수 있음 |
| 워커 / 배치 | 외부 API, 내부 큐 소비 속도 보호에 유리 | 사용자-facing 계약과는 별도 관리가 필요함 |
실무에서는 보통 다음 식의 조합이 많습니다.
- Edge: 거친 보호와 공통 남용 방지
- 서비스: 도메인별 세밀한 제한
- 워커: 외부 시스템 보호와 내부 폭주 완충
즉, 좋은 답변은 “게이트웨이에서 합니다”보다
어디에서 공통 보호를 하고, 어디에서 비즈니스 문맥 제한을 할지 나눈다는 쪽입니다.
관련 운영 배치는 API Gateway와 Edge 패턴 (API Gateway and Edge Patterns),
tenant별 정책은 멀티 테넌시 (Multi-Tenancy)와 연결해서 설명하면 좋습니다.
Quota, Abuse Protection, Backpressure의 차이
이 세 개는 비슷해 보이지만 질문이 다릅니다.
| 개념 | 질문 | 예시 |
|---|---|---|
| Rate Limit | 지금 이 짧은 시간 창에 얼마나 허용할 것인가 | 초당 10건 |
| Quota | 더 긴 기간에 총 얼마나 허용할 것인가 | 하루 100,000건 |
| Abuse Protection | 비정상 사용을 어떻게 차단할 것인가 | 봇, 브루트포스, 스크래핑 차단 |
| Backpressure | 소비 속도를 넘는 입력을 어떻게 완충할 것인가 | 큐 적체 시 drop, throttle, delay |
면접에서 이 차이를 구분하면 답변이 더 정교해집니다.
- rate limit은 단기 속도 제어
- quota는 계약과 요금제 제어
- abuse protection은 보안과 남용 방지
- backpressure는 시스템 내부 처리량 보호
즉, 레이트 리미팅 하나로 모든 문제를 해결한다고 말하면 범위가 섞이기 쉽습니다.
자주 하는 실수
- 기준 단위를 정하지 않고 “초당 N건”만 말함
- burst와 sustained limit을 구분하지 않음
429만 반환하고 재시도 계약을 설명하지 않음- 모든 엔드포인트에 같은 제한을 적용함
- 분산 환경에서 로컬 메모리 카운터만 믿음
- 레이트 리밋 저장소 장애 시 정책을 어떻게 할지 정하지 않음
- quota, abuse protection, backpressure를 한 개념처럼 섞어 설명함
면접 포인트
- 레이트 리미팅은 속도 제한 자체보다 보호 대상과 기준 단위를 먼저 정하는 문제입니다.
- IP, 사용자, 토큰, tenant는 서로 다른 보호 목적을 가지므로 함께 조합하는 경우가 많습니다.
429와Retry-After까지 설명하면 클라이언트 계약 관점이 살아납니다.- Fixed Window, Sliding Window, Token Bucket은 정확도와 비용의 선택지로 설명하는 편이 좋습니다.
- 분산 환경에서는 저장소 정확도, 원자성, 장애 시 동작을 함께 봐야 답변이 강해집니다.