Retry-After 헤더: 다시 시도하기 전에 얼마나 기다려야 하는지

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 처리하는 방법

  1. 두 형식을 모두 읽으세요. 값이 숫자이면 초입니다. 그렇지 않으면 날짜로 구문 분석하고 현재 시간을 뺍니다. 날짜가 이미 과거인 경우 즉시 다시 시도할 수 있습니다.
  2. 헤더가 말하는 한 적어도 기다립니다. 더 일찍 다시 시도하면 일반적으로 다른 오류(429 또는 503)가 발생합니다. 일부 API는 API가 요청을 제한하는 동안에도 요청을 계속 계산하므로 조기 재시도로 대기 시간이 길어질 수 있습니다. 예를 들어 Microsoft Graph 제한 지침을 참조하세요.
  3. 헤더가 누락된 경우 지터가 있는 백오프로 폴백합니다. 각 시도가 실패한 후 대기 시간을 두 배로 늘리고, 많은 클라이언트가 동시에 다시 시도하지 않도록 임의 금액을 추가하고 대기를 제한합니다.
  4. 재시도 횟수를 제한하세요. 몇 번의 시도 끝에 호출자에게 오류를 반환합니다.
  5. 재시도가 도움이 될 수 있는지 확인합니다. 크레딧 또는 지출 한도가 소진되면 일부 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가 사용자를 위해 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"

그런 다음 평소처럼 앱을 실행하고 어떻게 동작하는지 확인합니다. 개발 프록시를 설치하려면 개발 프록시 설정을 참조하세요.

다음 단계

또한, 다음을 참조하세요.