AI VIDEO BRIEFING

API 속도 제한(Rate Limiting) 원리와 429 대응·구현 방법 총정리

왜 API는 요청을 제한할까. 응답 헤더 읽는 법, 네 가지 제한 알고리즘, 지수 백오프와 지터, 그리고 직접 속도 제한을 구현하는 세 가지 위치를 정리했다.

HTTP 429를 만났을 때 — API 속도 제한의 원리와 직접 만드는 법 영상 대표 이미지

핵심 메시지

  • API가 요청을 제한하는 이유는 공정성(시끄러운 이웃 방지), 남용 방어, 비용 예측의 세 가지이며, 429는 무례함이 아니라 자기 보호다.
  • 재시도 로직을 짜기 전에 먼저 응답 헤더를 읽어야 한다. 표준인 Retry-After가 있으면 추측하지 말고 그대로 따른다.
  • 고정 윈도우, 슬라이딩 윈도우, 토큰 버킷, 누수 버킷 네 가지 알고리즘은 각각 동작이 다르며, 어떤 것에 걸렸는지 알면 대응법이 달라진다.
  • 클라이언트 측 대응은 Retry-After 준수, 지터를 더한 지수 백오프, 동시성 제한, 캐싱의 네 가지로 요약된다.
  • 직접 구현할 때는 앱(Redis), 엣지(Nginx), 전용 게이트웨이 세 위치 중 트래픽 특성에 맞게 고르고, 무엇을 기준으로 셀지와 지표 모니터링을 신경 써야 한다.

쉽게 이해하기

영상은 스크립트가 잘 돌다가 갑자기 HTTP 429(Too Many Requests)를 만나 작업이 실패하고 알림이 울리는 장면으로 시작한다. API가 망가진 게 아니라 속도 제한에 걸린 것이다. 발표자는 제한이 거는 쪽(클라이언트)과 만드는 쪽(서버) 양쪽을 모두 다룬다.

API가 요청을 조절하는 이유는 세 가지다. 첫째 공정성으로, 한 시끄러운 클라이언트가 모두를 느리게 만들지 않게 한다. 둘째 남용 방어로, 스크래핑·크리덴셜 스터핑·무차별 대입에 대한 1차 방어선이다. 셋째 비용으로, 모든 요청이 CPU·DB·유료 외부 API를 쓰기 때문에 제한이 청구서를 예측 가능하게 해준다.

재시도를 짜기 전에 서버가 헤더로 보내는 정보를 읽어야 한다. HTTP 표준인 Retry-After는 초 단위 숫자나 HTTP 날짜로 ‘언제 다시 오라’고 알려준다. X-RateLimit-Limit/Remaining/Reset는 표준은 아니고 널리 쓰이는 관례이며, Reset이 유닉스 타임스탬프인지 남은 초인지, 대소문자나 하이픈 표기가 API마다 다르므로 문서를 확인해야 한다. 이를 표준화하려는 IETF 초안도 진행 중이다.

제한을 거는 알고리즘은 네 가지다. 고정 윈도우는 구현이 쉽지만 경계에서 폭주가 가능하고, 슬라이딩 윈도우는 더 정확하지만 계산 비용이 크다. 토큰 버킷은 토큰이 일정 속도로 채워져 짧은 폭주를 허용하되 평균을 제한하는, 현대 게이트웨이의 가장 흔한 패턴이다. 누수 버킷은 큐에서 일정 속도로 빼내 출력을 매끄럽게 만든다. Remaining 값이 어떻게 변하는지를 보면 어떤 방식인지 구분할 수 있다.

후반부는 서버 입장에서 직접 구현하는 법이다. 앱 안에서는 Redis가 핵심으로, 단순 INCR+EXPIRE는 고정 윈도우이고, 진짜 토큰 버킷은 작은 Lua 스크립트로 경쟁 상태 없이 처리한다. 엣지에서는 Nginx limit_req로 코드 없이 누수 버킷 제한을 걸 수 있고, 트래픽이 커지면 Kong·Tyk·AWS API Gateway·Cloudflare 같은 전용 게이트웨이로 라우트·소비자·키별 제한과 분석을 얻는다.

주요 인사이트

  • 가장 나쁜 대응은 지연 없이 즉시 재시도하는 단순 루프다. 계속 429를 받을 뿐 아니라 IP나 API 키가 남용으로 표시될 수 있다.
  • 지수 백오프에는 ‘천둥 같은 무리(thundering herd)’ 문제가 있다. 100개 클라이언트가 동시에 실패해 같은 간격으로 동기화돼 재시도하면 장애가 더 길어진다. 해법은 각 지연에 무작위성을 더하는 지터이며, 0부터 백오프 값 사이를 무작위로 기다리는 ‘풀 지터’가 가장 단순하다.
  • 백오프는 이미 제한에 걸린 뒤의 대응이고, 동시성 제한은 애초에 걸리지 않게 막는 방법이다. 초당 10요청이 한도라면 50개를 한꺼번에 던지지 말고 세마포어나 큐로 동시 실행 수를 묶어야 한다.
  • 가장 빠른 요청은 아예 보내지 않는 요청이다. Cache-Control, ETag, If-None-Match와 304 Not Modified를 활용한 캐싱은 화려하지 않지만 목록에서 레버리지가 가장 큰 전술이며, 작은 TTL 캐시만으로도 요청량을 한 자릿수 배 줄일 수 있다.
  • 직접 만들 때 무엇을 기준으로 셀지가 중요하다. IP 기준은 쉽지만 NAT 뒤의 사무실·통신사 사용자를 함께 벌하고, API 키나 사용자 기준이 더 낫다. 실무 시스템은 남용용 IP 단위와 공정성용 사용자 단위를 함께 쌓는다.

자주 묻는 질문

Retry-After 헤더가 있으면 어떻게 해야 하나요?

추측하지 말고 그대로 따르라는 것이 영상의 조언이다. 서버는 429나 503에 Retry-After를 담아 정확히 얼마나 기다려야 하는지 초 단위 숫자나 HTTP 날짜로 알려주며, 언제 준비되는지는 클라이언트보다 서버가 더 잘 안다.

Nginx로 속도 제한을 걸 때 주의할 점은 무엇인가요?

Nginx limit_req는 기본적으로 거부 시 429가 아니라 503(Service Unavailable)을 반환한다. 대부분의 클라이언트는 429를 기대하므로, 표준 상태 코드를 원하면 limit_req_status 429를 명시해야 한다.

속도 제한이 잘 동작하는지 어떻게 알 수 있나요?

세 가지 지표를 대시보드로 본다. 429 비율(건강한 API는 작지만 0이 아니다), 재시도 예산(구글 SRE 책 기준 전체의 10%를 넘으면 클라이언트가 백오프 루프에 갇힌 것), 그리고 429 후 대기 시간(치솟으면 제한이 너무 빡빡하거나 리필 로직이 깨진 것)이다.

원문과 출처

이 글은 원본 영상의 자막을 바탕으로 한국어 독자를 위해 요약했습니다. 전체 맥락과 최신 정보는 원문에서 확인하세요.

YouTube 원본 영상 보기 ↗

관련 AI 소식

#API#Rate Limiting#백엔드#HTTP#Redis