🤖 AI 생성 콘텐츠 — 이 글은 AI가 자료를 수집하고 초안을 작성했으며, 발행 전 누슘 운영자가 검수했습니다.
API를 쓰다 보면 만나는 ‘429 Too Many Requests’ 에러. 서버가 요청을 세는 방식(레이트 리밋)에 따라 이 에러가 언제 뜨는지가 완전히 달라집니다. 토큰 버킷·리키 버킷·슬라이딩 윈도우를 물통 비유로 쉽게 정리했습니다.
API를 좀 써봤다면 한 번쯤 만나는 숫자가 있습니다. 429. “Too Many Requests” — 너무 많이 요청했다는 뜻이죠. 근데 이상하지 않나요? 어떤 API는 짧게 몰아치면 봐주는데, 어떤 API는 딱 그 순간 429를 뱉습니다. 같은 ‘요청 제한’인데 왜 반응이 다를까요?
결론부터 말하면 — 서버가 요청을 세는 방식(rate limiting, 레이트 리밋)이 다르기 때문입니다. 방식은 크게 네 가지. 토큰 버킷, 리키 버킷, 고정 윈도우, 슬라이딩 윈도우. 이름은 딱딱하지만 전부 ‘물통’과 ‘시간 상자’로 풀면 쉽습니다. 오늘 이 네 개만 잡으면 429가 왜, 언제 뜨는지 감이 옵니다.
목차
- 레이트 리밋이 왜 필요한가
- 토큰 버킷: 물통에 토큰이 찬다
- 리키 버킷: 밑이 새는 물통
- 고정 윈도우 vs 슬라이딩 윈도우
- 그래서 뭘 써야 하나
- 429를 만났을 때 (FAQ)
레이트 리밋이 왜 필요한가
레이트 리밋은 한마디로 “일정 시간에 이만큼만 받을게” 하는 규칙입니다. 이게 없으면 어떻게 될까요? 한 사용자가 초당 수천 번 두드리면 서버가 그 사람 하나 때문에 뻗고, 나머지 정상 사용자가 다 피해를 봅니다. 악의적 공격이 아니어도 버그난 코드가 무한루프로 API를 때리는 사고도 흔합니다.
그래서 서버는 한도를 넘는 요청을 거절하고 클라이언트에게 429를 돌려줍니다. 이때 잘 만든 API는 응답에 Retry-After 헤더를 같이 보냅니다. “몇 초 뒤에 다시 와” 하고 알려주는 거죠. 클라이언트는 이걸 보고 얌전히 기다렸다가 재시도하면 됩니다. 무작정 계속 두드리면 서버 부하만 키우니까요.

토큰 버킷: 물통에 토큰이 찬다
가장 널리 쓰이는 방식입니다. 비유는 이렇습니다.
물통(bucket)이 하나 있고, 거기에 토큰이 일정 속도로 똑똑 떨어집니다. 통에는 최대 용량이 있어서 넘치면 그냥 버려집니다. 요청이 하나 올 때마다 통에서 토큰을 하나 꺼내 씁니다. 토큰이 있으면 통과, 없으면 429.
여기서 재밌는 특징 하나. 한동안 요청을 안 보내면 토큰이 통에 쌓여 있습니다. 그러다 갑자기 요청이 몰리면? 쌓아둔 토큰만큼은 한꺼번에 받아줍니다. 즉 짧은 순간의 폭주(burst)를 허용하는 거죠. 평균적으로는 엄격하되, 잠깐의 스파이크는 봐주는 성격입니다. “평소 아껴 쓴 사람에게는 관대한” 방식이라고 보면 됩니다.
리키 버킷: 밑이 새는 물통
이름 그대로 밑에 구멍이 난 물통입니다. 요청이 위에서 통으로 들어가고, 통은 일정한 속도로만 밑으로 새어 나갑니다(처리됩니다). 물이 새는 속도는 고정. 요청이 아무리 몰려도 나가는 속도는 그대로입니다.
통이 꽉 차면 넘치는 요청은 버려집니다(429). 토큰 버킷과 결정적으로 다른 점은 — 폭주를 허용하지 않는다는 겁니다. 들어오는 게 아무리 울퉁불퉁해도 나가는 흐름은 매끈하게 일정합니다. 그래서 뒤에 붙은 시스템(예: 결제 처리, DB 쓰기)이 갑작스러운 부하를 감당 못 할 때 이 방식이 잘 맞습니다. 트래픽을 평탄하게 다림질해서 내보내니까요.

고정 윈도우 vs 슬라이딩 윈도우
이번엔 ‘시간 상자’로 세는 방식입니다.
고정 윈도우(fixed window)는 시간을 딱딱 끊어 셉니다. “매 분 100개까지” 하면 12:00:00~12:00:59에 100개, 다음 분이 되면 카운터를 0으로 리셋. 단순하고 빠릅니다. 근데 함정이 있습니다. 경계에서 새는 겁니다. 12:00:59에 100개, 12:01:00에 또 100개를 보내면 2초 사이에 200개가 통과합니다. 규칙은 지켰는데 서버는 순간 폭주를 맞는 거죠.
슬라이딩 윈도우(sliding window)는 이 문제를 메꿉니다. 상자를 고정하지 않고, “지금 이 순간부터 뒤로 N초”를 계속 미끄러뜨리며 셉니다. 요청 시각들을 기록해 두고, 최근 N초 안에 몇 개인지 매번 다시 셉니다. 경계 폭주가 사라지고 훨씬 매끄럽게 제한됩니다. 대신 시각 기록을 관리해야 해서 비용이 조금 더 듭니다.
| 방식 | 비유 | 버스트 허용 | 특징 |
|---|---|---|---|
| 토큰 버킷 | 토큰이 차는 물통 | 있음(쌓인 만큼) | 평균 엄격, 짧은 스파이크 관대 |
| 리키 버킷 | 밑이 새는 물통 | 없음 | 출력 속도 일정, 트래픽 평탄화 |
| 고정 윈도우 | 시간 상자 리셋 | 경계에서 샘 | 단순·빠름, 경계 폭주 취약 |
| 슬라이딩 윈도우 | 미끄러지는 시간 창 | 거의 없음 | 정확·매끄러움, 관리 비용↑ |
그래서 뭘 써야 하나
정답은 “상황에 따라”지만, 실무의 대략적인 결이 있습니다. 공개 API의 가장 무난한 기본값은 슬라이딩 윈도우로 보는 시각이 많습니다. 경계 폭주 없이 안정적이니까요. 평소 안 쓰던 고객에게 잠깐의 여유를 주고 싶으면 토큰 버킷, 뒤에 붙은 시스템이 갑작스러운 부하를 못 견디면 리키 버킷이 어울립니다. 실제로 상용 API 상당수가 토큰 버킷 아니면 슬라이딩 윈도우를 씁니다.
정리하면 — “요청을 어떻게 세느냐”가 곧 “폭주를 얼마나 봐주느냐”입니다. 그 성격 차이가 여러분이 만나는 429의 타이밍을 결정합니다.
자주 묻는 질문 (FAQ)
Q. 429 에러가 뜨면 개발자가 뭘 해야 하나요?
A. 우선 응답의 Retry-After 헤더를 확인하세요. 서버가 “몇 초 뒤 다시 오라”고 알려주면 그만큼 기다렸다가 재시도합니다. 헤더가 없으면 지수 백오프(exponential backoff) — 실패할 때마다 대기 시간을 2배씩 늘리는 방식 — 로 재시도하는 게 정석입니다. 실패하자마자 곧바로 다시 두드리면 서버 부하만 키웁니다.
Q. 토큰 버킷과 리키 버킷, 헷갈리는데 한 줄 차이는? A. 토큰 버킷은 쌓아둔 토큰으로 잠깐의 폭주를 허용합니다. 리키 버킷은 출력 속도를 무조건 일정하게 유지해 폭주를 허용하지 않습니다. “잠깐 몰아치는 걸 봐줄 거냐 말 거냐”가 갈림길입니다.
Q. 고정 윈도우는 왜 위험하다고 하나요? A. 시간 경계에서 카운터가 리셋되기 때문입니다. 한 창의 끝과 다음 창의 시작에 요청을 몰면, 짧은 순간에 한도의 최대 2배가 통과할 수 있습니다. 이 ‘경계 폭주’가 싫으면 슬라이딩 윈도우를 씁니다.
Q. 레이트 리밋은 서버에서만 하나요? A. 아닙니다. 클라이언트도 스스로 속도를 조절(client-side rate limiting)하면 불필요한 429와 재시도를 줄일 수 있습니다. 서버 한도를 미리 알고 그 안에서 요청을 흘려보내면 양쪽 다 편해집니다.
마치며
레이트 리밋은 눈에 잘 안 보이지만, API를 쓰는 사람이라면 반드시 만나는 벽입니다. 오늘 네 가지 — 토큰 버킷, 리키 버킷, 고정/슬라이딩 윈도우 — 의 성격만 기억해도, 429가 떴을 때 “아, 이 서버는 이렇게 세는구나” 하고 감이 옵니다. IT·컴퓨터 게시판을 보는 개발자분들, 직접 서비스에 레이트 리밋을 붙여본 경험이 있다면 어떤 방식을 왜 골랐는지 댓글로 공유해 주세요. 다음 개발 글에서는 재시도의 정석인 ‘지수 백오프와 지터’를 따로 다뤄보겠습니다.
참고자료
- Rate Limiting Algorithms: Token Bucket vs Sliding Window vs Fixed Window (Arcjet)
- Rate Limiting Deep Dive: Token Bucket vs Leaky Bucket vs Sliding Window (DEV Community)
- Rate Limiting Algorithms – System Design (GeeksforGeeks)
- Mastering API Rate Limiting (Moesif)
태그: #레이트리밋 #RateLimiting #토큰버킷 #리키버킷 #슬라이딩윈도우 #API #백엔드 #429에러

댓글을 남기려면 로그인이 필요합니다.
로그인하고 댓글 남기기