Retry-After 는 앱이 다음 요청을 보내기 전에 대기하는 시간을 알려주는 HTTP 응답 헤더입니다. 값은 초 단위 숫자이거나 HTTP 날짜입니다. 이는 API가 이를 보낼 경우 요청을 거절한 서버에서 제공되기 때문에 "언제 다시 시도할 수 있습니까?"에 대한 가장 신뢰할 수 있는 대답입니다. 자세한 내용은 RFC 9110, 섹션 10.2.3을 참조하세요.
Retry-After의 형식
헤더에는 2개의 형식이 있습니다. 앱이 둘 다 처리해야 합니다.
| Format | Example | 의미 |
|---|---|---|
| Seconds | Retry-After: 120 |
응답을 받은 시점부터 120초(2분) 기다립니다. 값은 음수가 아닌 정수입니다. |
| HTTP 날짜 | Retry-After: Fri, 31 Dec 1999 23:59:59 GMT |
이 시간 전에 요청을 다시 보내지 마세요. 시간은 항상 GMT입니다. |
서버는 다음 상태 코드와 함께 Retry-After를 보냅니다.
| 상태 |
Retry-After의 의미 |
Source |
|---|---|---|
429 Too Many Requests |
새 요청을 보내기 전에 대기하는 기간입니다. 서버가 이를 포함할 수 있습니다. | RFC 6585, 섹션 4 |
503 Service Unavailable |
서비스를 사용할 수 없을 것으로 예상되는 기간입니다. 서버에 포함할 수 있습니다. | RFC 9110, 섹션 15.6.4 |
413 Content Too Large |
조건이 일시적이면 서버는 얼마나 후에 끝나는지 알려야 합니다. | RFC 9110, 섹션 15.5.14 |
임의의 3xx 리디렉션 |
리디렉션을 따르기 전에 대기할 최소 시간입니다. | RFC 9110, 섹션 10.2.3 |
헤더는 선택 사항입니다. 일부 API는 자체 헤더를 대신 사용합니다. 예를 들어 GitHub 제한이 다시 설정되면 x-ratelimit-reset알려줍니다. 자세한 내용은 GitHub API rate limit exceeded를 참조하세요.
Retry-After 처리하는 방법
- 두 형식을 모두 읽으세요. 값이 숫자이면 초입니다. 그렇지 않으면 날짜로 구문 분석하고 현재 시간을 뺍니다. 날짜가 이미 과거인 경우 즉시 다시 시도할 수 있습니다.
- 헤더가 말하는 한 적어도 기다립니다. 더 일찍 다시 시도하면 일반적으로 다른 오류(
429또는503)가 발생합니다. 일부 API는 API가 요청을 제한하는 동안에도 요청을 계속 계산하므로 조기 재시도로 대기 시간이 길어질 수 있습니다. 예를 들어 Microsoft Graph 제한 지침을 참조하세요. - 헤더가 누락된 경우 지터가 있는 백오프로 폴백합니다. 각 시도가 실패한 후 대기 시간을 두 배로 늘리고, 많은 클라이언트가 동시에 다시 시도하지 않도록 임의 금액을 추가하고 대기를 제한합니다.
- 재시도 횟수를 제한하세요. 몇 번의 시도 끝에 호출자에게 오류를 반환합니다.
- 재시도가 도움이 될 수 있는지 확인합니다. 크레딧 또는 지출 한도가 소진되면 일부 API는
429을 반환합니다. 기다려도 그것들은 해결되지 않습니다. 예제는 OpenAI insufficient_quota 및 credit_balance_exhausted 참조하세요.
function retryDelayMs(response, attempt) {
const value = response.headers.get('retry-after');
if (value) {
const seconds = Number(value);
const ms = Number.isNaN(seconds) ? Date.parse(value) - Date.now() : seconds * 1000;
if (!Number.isNaN(ms)) {
return Math.max(ms, 0);
}
}
// No usable header: exponential backoff with jitter, capped at 30 seconds
return Math.random() * Math.min(30_000, 1_000 * 2 ** attempt);
}
인기 있는 SDK의 기능
많은 SDK가 사용자를 위해 Retry-After를 처리하지만 재시도 횟수를 모두 소진할 때까지만 처리합니다. 그러면 코드에 오류가 발생합니다.
| SDK | 기본적으로 수행하는 기능 |
|---|---|
| .NET 표준 복원력 처리기 | 지수 백오프 및 지터를 사용하여 5xx, 408, 및 429 응답을 최대 3회까지 재시도합니다.
true의 기본값이 Retry-After이므로 지연에는 ShouldRetryAfterHeader를 사용합니다. |
| Microsoft Graph SDK | 존재할 때 사용하고 Retry-After , 그렇지 않은 경우 지수 백오프로 대체합니다. JSON 일괄 처리 내의 요청은 자동으로 다시 시도되지 않습니다. |
| OpenAI Python SDK | 짧은 지수 백오프를 사용하여 연결 오류 및 408, 409429및 5xx 응답을 2번 다시 시도합니다. 변경하도록 설정합니다 max_retries . |
정확한 정책에 대한 SDK 설명서를 확인하고 마지막 재시도가 실패한 후 어떤 일이 발생하는지 테스트합니다.
앱이 Retry-After를 처리하는지 테스트하는 방법
개발 중에는 Retry-After 값을 거의 얻을 수 없으며, 어쩌다 얻더라도 그 값은 제어할 수 없습니다. 따라서 이를 테스트하는 방법은 사용자가 하기 전에 버그를 찾을지 여부를 결정합니다.
| Approach | 찾은 내용 | 놓친 내용 |
|---|---|---|
| 프로덕션을 기다리세요 | 실제 실패 | 사용자가 그것을 누르기 전까지는 모든 것 |
| 테스트에서 API를 모킹하거나 코딩 에이전트가 모의 객체를 만들도록 허용 | 코드에서 헤더를 구문 분석하는지 여부 | 실제 HTTP 클라이언트 또는 SDK가 충분히 오래 대기하는지 여부와 API가 실제로 전송하는 내용 또한 mock에 접근하려면 앱에 테스트 전용 스위치가 필요합니다. |
| 제한이 걸릴 때까지 실제 API를 호출하세요 | 실제 동작 | 요청 시 제한된 응답을 트리거할 수 없으며 실제 할당량을 소진합니다. |
| 앱의 실제 트래픽을 가로채고 요청 시 속도 제한된 응답을 반환합니다. | 헤더에 명시된 시간만큼 실제 SDK와 재시도 정책이 대기하는지 여부 | 앱에서 아무것도 변경되지 않으므로 코드를 격리된 상태로 테스트하지 않습니다. 그건 단위 테스트로 확인하세요. |
앱에서 시도해 보기
Dev Proxy는 선택한 API에 대한 앱의 요청을 가로채고, 앱이 실제 URL을 계속 호출하는 동안 Retry-After응답을 429헤더와 함께 반환합니다.
RetryAfterPlugin은 제한된 각 요청을 다시 시도할 수 있는 시기를 기억합니다. 앱이 해당 시간 전에 동일한 URL을 호출하는 경우 Dev Proxy는 이를 보고하고 요청을 다시 제한합니다. 플러그인은 429 응답만 추적합니다.
GenericRandomErrorPlugin에 대한 오류 파일에서 Retry-After 응답의 429 값을 @dynamic(으)로 설정하면 Dev Proxy가 초 수를 채우고 자동으로 추적해 줍니다.
이를 시도하려면 두 플러그인을 모두 사용하는 사전 설정을 다운로드하고 그 사전 설정으로 Dev Proxy를 시작합니다.
devproxy config get openai-throttling
devproxy --config-file "~dataFolder/configs/openai-throttling/.devproxy/devproxyrc.json"
그런 다음 평소처럼 앱을 실행하고 어떻게 동작하는지 확인합니다. 개발 프록시를 설치하려면 개발 프록시 설정을 참조하세요.
다음 단계
또한, 다음을 참조하세요.
Dev Proxy