이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- 사용자별, IP별, API별, tenant별 제한 기준은 어떤 상황에 맞는가?
- 제한 정책이 공정성, 보안, 비용, 장애 격리를 어떻게 바꾸는가?
- 정상 사용자를 과하게 막지 않으면서 비싼 요청과 남용을 어떻게 분리하는가?
개요
Rate Limit 정책에서 가장 어려운 부분은 숫자가 아니라 기준이다. “분당 60회”보다 먼저 정해야 할 것은 누구를 기준으로 세고, 어떤 API를 하나의 제한 그룹으로 볼지다.
로그인 API는 IP와 계정 기준이 중요할 수 있고, 결제 API는 userId와 주문 idempotency가 중요하다. Public API는 API key와 tenant 기준이 자연스럽고, 관리자 export는 job과 tenant 기준으로 제한해야 할 수 있다.
모든 사용자를 같은 제한으로 막으면 단순하지만 공정하지 않다. 모든 예외를 허용하면 정책이 무력화된다.
제한 기준
| 기준 | 적합한 상황 | 위험 |
|---|---|---|
| IP | 익명 요청, 로그인 공격 | NAT 환경에서 정상 사용자가 함께 막힌다 |
| userId | 로그인 사용자 기능 | 계정 탈취 시 남용이 가능하다 |
| API key | partner/public API | key 공유와 유출 대응이 필요하다 |
| tenant | B2B SaaS 비용 보호 | tenant 내부 사용자 차이를 놓친다 |
| endpoint | 비싼 API 보호 | 같은 사용자의 전체 남용을 놓친다 |
| device/session | 앱 클라이언트 제어 | 식별자 재발급으로 우회 가능하다 |
좋은 정책은 하나의 기준만 쓰지 않는다. 로그인은 IP + 계정, export는 tenant + user + job, 결제는 user + orderId처럼 조합한다.
API별 비용
API마다 비용이 다르다.
GET /products 낮은 비용, cache 가능
GET /search 중간 비용, 검색 엔진 사용
POST /orders 높은 비용, 재고/결제/DB write
POST /exports 매우 높은 비용, batch와 storage 사용
POST /login 보안 위험이 높은 비용같은 100회 요청이라도 상품 조회 100회와 export 100회는 시스템 비용이 다르다. API별 제한은 이 비용 차이를 정책으로 드러낸다.
정책 매트릭스
| API | 기준 key | 기본 제한 | 초과 응답 | 이유 |
|---|---|---|---|---|
| 로그인 | IP + account | 5/min | 429 또는 captcha | brute force 완화 |
| 검색 | userId | 60/min | 429 + Retry-After | 검색 비용 보호 |
| 주문 생성 | userId + itemId | 1/sec | 409 또는 429 | 중복 주문 방어 |
| 결제 요청 | userId + orderId | idempotency | 동일 결과 반환 | 중복 결제 방어 |
| Export | tenant + jobType | 3 active jobs | 202 pending 또는 429 | batch 자원 보호 |
이 표는 숫자보다 판단을 보여준다. 어떤 API는 429가 맞고, 어떤 API는 같은 idempotency key에 기존 결과를 반환하는 것이 맞다.
무료/유료/VIP 정책
요금제별 제한은 공정성과 비용 회수의 문제다.
Free: 60 requests / minute
Pro: 600 requests / minute
Enterprise: 계약별 quota
Internal batch: 낮은 우선순위 queue하지만 VIP를 무제한으로 두면 장애 때 전체 시스템을 흔들 수 있다. 높은 quota를 주더라도 절대 상한, downstream 보호, emergency brake는 필요하다.
정책 저장과 변경
제한 정책은 코드에 박아 두면 운영 중 조정이 어렵다. 하지만 완전히 동적으로 만들면 감사와 검증이 어려워진다.
실용적인 구조는 다음과 같다.
rateLimits:
search:
free: {limit: 60, window: 60s}
pro: {limit: 600, window: 60s}
export:
free: {concurrency: 1}
pro: {concurrency: 3}정책 변경에는 version, 변경자, 이유, 적용 시각이 남아야 한다. 장애 중 임시 완화도 나중에 회고할 수 있어야 한다.
공정성 문제
IP 기준 제한은 단순하지만 회사, 학교, 공용 와이파이처럼 많은 사용자가 같은 IP를 공유하는 환경에서 정상 사용자를 함께 막을 수 있다.
반대로 userId 기준만 쓰면 로그인 전 공격을 막기 어렵고, 새 계정을 계속 만드는 남용도 막기 어렵다.
따라서 기준은 사용자 식별 가능성에 따라 달라진다.
로그인 전: IP, device fingerprint, account name
로그인 후: userId, tenant, plan
파트너 API: API key, client id, tenant
내부 작업: job type, service account, priority정책 우회
제한은 우회될 수 있다.
- API key를 여러 개 발급한다.
- userId를 여러 개 만든다.
- IP를 분산한다.
- endpoint를 바꿔 같은 비용 작업을 호출한다.
- retry client가 제한 직후 즉시 재시도한다.
정책은 완벽한 차단이 아니라 비용을 높이고 피해 반경을 줄이는 장치다. 남용 탐지, anomaly detection, billing, abuse review와 함께 봐야 한다.
클라이언트별 계약
브라우저, 모바일 앱, partner API는 제한 응답을 다르게 소비한다.
| 클라이언트 | 필요한 정보 |
|---|---|
| 브라우저 | 사용자 메시지와 다시 시도 가능 시간 |
| 모바일 앱 | retry delay와 UI 상태 |
| partner API | quota limit, remaining, reset |
| 내부 batch | job 재스케줄 기준과 priority |
Partner API에는 RateLimit-Remaining 같은 quota 정보를 주는 것이 유용할 수 있다. 일반 사용자 화면에는 숫자보다 “잠시 후 다시 시도”와 대기 시간이 더 중요하다.
위험 신호
- IP 기준 하나로 로그인, 검색, 주문, 결제를 모두 제한한다.
- VIP나 내부 batch가 무제한으로 핵심 API를 호출한다.
- 정책 변경 이력과 승인자가 없다.
- 429 증가를 남용 차단 성공으로만 보고 정상 사용자 피해를 보지 않는다.
- 결제 중복 방어를 rate limit으로만 해결하려 한다.
개인 프로젝트 기준
- 최소 두 API에 서로 다른 제한 기준을 둔다.
- 로그인은 IP 기준, 사용자 기능은 userId 기준처럼 이유를 적는다.
- 정책 값을 설정 파일로 분리한다.
- 제한 로그에 key, endpoint, decision을 남긴다.
기업 운영 기준
- plan, tenant, endpoint별 정책 matrix를 관리한다.
- 예외 정책은 만료일과 승인자를 둔다.
- abuse 대응과 customer support가 같은 quota 정보를 볼 수 있게 한다.
- 제한으로 인한 매출, 전환, SLA 영향을 함께 본다.
확인 질문
확인 질문
- 확인 질문: 모든 API에 같은 제한을 적용하면 왜 위험한가?
- 답변: API별 비용과 사용자 기대, 보안 위험이 달라서 어떤 API는 과하게 막히고 어떤 API는 충분히 보호되지 않기 때문이다.
- 확인 질문: IP 기준 제한의 대표적인 부작용은 무엇인가?
- 답변: NAT나 공용 네트워크 뒤의 정상 사용자들이 한 사용자처럼 묶여 함께 차단될 수 있다.
- 확인 질문: 결제 중복을 rate limit만으로 막으면 부족한 이유는 무엇인가?
- 답변: 네트워크 재시도와 중복 클릭은 제한 사이에도 발생할 수 있으므로 idempotency key와 동일 결과 반환이 필요하다.