API는 앱이 일정 기간 동안 API에서 허용하는 것보다 더 많은 요청을 보내면 429 Too Many Requests를 반환합니다. 요청 자체는 괜찮습니다. 너무 자주 전송했기 때문에 API가 요청을 거부했습니다. 기다렸다가 다시 보내면 일반적으로 성공합니다. 응답에는 대기 시간을 알려주는 Retry-After 헤더가 포함되어 있는 경우가 많습니다. 자세한 내용은 RFC 6585 섹션 4를 참조하세요.
인기 있는 API의 429 응답 예시
모든 API는 요청 제한을 다르게 구현합니다. 상태 코드, 헤더 및 오류 본문은 모두 다르므로 한 API를 올바르게 처리하는 코드는 다음 API를 잘못 처리할 수 있습니다.
| API | 상태 | 얼마나 오래 기다려야 하는지 확인하는 방법 | 조심하세요 |
|---|---|---|---|
| GitHub |
403 또는 429 |
retry-after가 있는 경우, 그렇지 않으면 x-ratelimit-remaining가 0일 때는 x-ratelimit-reset (UTC epoch 초), 그렇지 않으면 적어도 1분 |
403은 속도 제한 또는 누락된 권한일 수 있습니다. 헤더를 읽고 구분하세요. |
| OpenAI | 429 |
retry-after |
일부 429(예: credit_balance_exhausted)는 다시 시도해도 도움이 되지 않음을 의미합니다.
error.code를 확인합니다. |
| Anthropic | 429 |
retry-after |
지출 한도 429에는 retry-after가 없고 액세스가 재개될 때까지 계속 실패합니다. 오버로드된 API는 529가 아니라 429를 반환합니다. |
| Microsoft Graph | 429 |
Retry-After(초) |
제한은 서비스마다 다릅니다(예: SharePoint 및 Outlook). |
429를 처리하는 방법
- 다시 시도할지 여부를 결정하세요. 할당량, 크레딧 또는 지출 한도가 소진되었다는 오류가 표시되면 다시 시도하는 것은 도움이 되지 않습니다. 사용자에게 알리고 자신에게도 경고하세요.
- API가 요청하는 만큼 기다리세요. 응답에
Retry-After이 있으면 그만큼 기다립니다. 몇 초이거나 HTTP 날짜입니다. API가 GitHub의x-ratelimit-reset처럼 요청 한도 헤더를 대신 사용하는 경우 재설정 시간까지 기다립니다. - 그렇지 않으면 물러서십시오. API의 힌트가 없으면 지수 백오프 및 임의 지터를 사용하여 다시 시도하고 몇 번의 시도 후에 중지합니다.
- 사용자에게 무슨 일이 일어나고 있는지 알려주세요. "사용 중, 5초 후 다시 시도"는 끝없이 도는 스피너보다 낫다.
- 다음 429 오류가 발생하기 전에 속도를 줄이세요. API가 속도 제한 헤더를 보내는 경우 나머지 개수를 사용하여 요청 속도를 조절합니다.
async function fetchWithRetry(url, options, attempts = 3) {
for (let attempt = 1; ; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429 || attempt === attempts) {
return response;
}
const retryAfter = response.headers.get('retry-after');
const waitMs = retryAfter
? (isNaN(retryAfter) ? new Date(retryAfter) - Date.now() : retryAfter * 1000)
: 2 ** attempt * 1000 + Math.random() * 1000;
await new Promise(resolve => setTimeout(resolve, Math.max(waitMs, 0)));
}
}
많은 SDK가 429 오류 응답 요청을 자동으로 재시도합니다. 예를 들어 OpenAI Python SDK는 기본적으로 2번 재시도하고 .NET 표준 복원력 처리기는 3번 다시 시도하고 Retry-After을(를) 따릅니다. SDK가 재시도 횟수를 모두 소진하면 코드에서 오류가 발생하므로 여전히 계획이 필요합니다.
앱이 429를 처리하는지 테스트하는 방법
개발하는 동안 429는 거의 표시되지 않습니다. API는 빠르고, 사용자가 본인뿐이고, 테스트 데이터는 작습니다. 따라서 429 처리를 테스트하는 방법은 사용자보다 먼저 버그를 발견할지 여부를 결정합니다.
| Approach | 찾은 내용 | 당신이 놓친 것 |
|---|---|---|
| 프로덕션을 기다리세요 | 실제 실패 | 사용자가 그것을 누르기 전까지는 모든 것 |
| 테스트에서 API를 모킹하거나 코딩 에이전트가 모의 개체를 작성하도록 허용 | 재시도 분기 실행 여부 | API의 실제 상태 코드, 헤더 및 오류 본문, 그리고 SDK의 재시도 정책 또한 mock에 도달하려면 앱에 테스트 전용 스위치가 필요합니다. |
| 실제 API를 제한이 걸릴 때까지 호출하세요 | 실제 동작 | 임의로 429를 트리거할 수 없으며 실제 할당량을 소모합니다. |
| 앱의 실제 트래픽을 가로채고 요청 시 429를 반환합니다. | 실제 URL, 실제 SDK 및 재시도 정책 및 API 고유의 429 형식 | 앱에서 아무것도 변경되지 않으므로 앱이 코드를 격리된 상태로 테스트하지 않습니다. 그럴 때는 단위 테스트를 사용하세요. |
앱에서 시도해 보기
Dev Proxy는 선택한 API에 대한 앱의 요청을 가로채고 API 자체 헤더 및 오류 형식을 사용하여 429를 반환하며 앱은 실제 URL을 계속 호출합니다. 또한 시간 Retry-After이 다 되기 전에 앱이 다시 시도하는 경우도 알려줍니다.
앱이 호출하는 API에 대한 사전 설정을 다운로드하고, 이를 사용하여 Dev Proxy를 시작합니다.
devproxy config get github-rate-limiting
devproxy --config-file "~dataFolder/configs/github-rate-limiting/.devproxy/devproxyrc.json"
| API | Preset |
|---|---|
| GitHub | github-rate-limiting |
| OpenAI | openai-throttling |
| Anthropic | anthropic-throttling |
Microsoft Graph(OneDrive 및 SharePoint: /drive, /shares, /sites) |
microsoft-graph-rate-limiting |
그런 다음 평소와 같이 앱을 실행하고 어떻게 동작하는지 확인합니다. 개발 프록시를 설치하려면 개발 프록시 설정을 참조하세요.
다음 단계
또한, 다음을 참조하세요.
Dev Proxy