AI 에이전트 API 재시도: 429·5xx와 403을 다르게 처리하기

최종 업데이트 2026.10.05

에이전트 API의 일시 오류와 권한 오류를 구분하는 재시도 정책을 로컬 상태열로 검증합니다. 429→500→200과 403의 실행 기록, 실제 화면 영상, 최대 3회 코드와 중복 요청·Retry-After·시간 초과의 한계를 설명합니다.

AI 에이전트의 API 재시도는 오류 종류와 최대 횟수를 먼저 정해야 합니다. 고정 상태열을 쓰는 로컬 시뮬레이터에서 429·500의 재시도와 403의 즉시 중단을 비교했습니다.

요청 실패를 모두 같은 문제로 취급하면 생기는 일

자동화가 실패했다는 메시지만 보고 같은 요청을 반복하면 일시적인 서버 장애와 잘못된 권한을 구분하지 못합니다. 호출할 때마다 비용이나 외부 변경이 생기는 작업이라면 반복 자체가 새로운 문제가 됩니다. 먼저 오류를 어떤 범주로 처리할지 정하고, 횟수가 아니라 전체 실행 시간과 결과의 확실성도 확인해야 합니다.

이 글의 교육용 정책은 429와 500~599를 재시도 후보로 보고 그 밖의 비성공 상태는 즉시 중단하는 것입니다. 전체 시도는 처음 요청을 포함해 최대 세 번으로 제한합니다. 요청 사이의 대기 정책은 1초, 2초입니다. 실제 외부 API를 호출하거나 LLM을 실행하지 않고 고정된 상태열을 함수에 넣어 분기와 종료 조건만 실습했습니다. 특정 서비스가 이 정책을 그대로 권장한다고 해석해서는 안 됩니다.

HTTP 상태와 Retry-After를 읽는 기준

MDN의 Response.status는 응답 객체에서 HTTP 상태 코드를 읽는 방법을 설명합니다. Retry-After 안내는 서버가 다음 요청까지 기다릴 시간을 날짜 또는 초 단위로 전달할 수 있음을 설명합니다. 실제 클라이언트는 서비스별 오류 문서와 이런 응답 정보를 함께 읽어야 합니다.

고정된 지수 대기만 쓰는 예제는 정책을 이해하기 위한 최소 코드입니다. 운영 환경에서는 서버가 반환한 Retry-After, 최대 대기 시간, 임의 지연을 더한 분산 처리와 서비스의 호출 제한을 고려해야 합니다. 연결 시간 초과는 HTTP 응답 자체가 없는 상황일 수 있으므로 상태 코드 배열만으로 표현되지 않습니다. 응답이 없었다는 사실과 서버가 요청을 처리하지 않았다는 사실은 같지 않다는 점이 중복 방지 설계에 중요합니다.

직접 실행 결과: 성공 경로와 권한 오류 경로

검증일 2026-10-01, 환경 Windows Chromium 1200×675, 입력값은 먼저 403,200입니다. 직접 검사하면 첫 403에서 blocked가 되고 총 시도는 1회입니다. 배열 뒤의 200은 소비하지 않았습니다. 권한 오류를 재시도해 성공한 것처럼 보여 주지 않도록 설계한 결과입니다.

수정 예제 429,500,200을 적용한 뒤 다시 검사했습니다. 화면에는 시도 1의 429, 시도 2의 500, 시도 3의 200과 success가 표시됐고 대기 정책은 1초와 2초로 계산됐습니다. 영상은 실제 버튼 조작과 이 출력 변화입니다. 이 시뮬레이터는 정책값을 계산하며 실제로 3초 동안 외부 요청을 기다리는 네트워크 시험이 아닙니다. 외부 서버의 복구 시간이나 서비스 성능에 대한 결과로 사용할 수 없습니다.

AI 에이전트 API 재시도: 429·5xx와 403을 다르게 처리하기의 실제 입력 화면
2026-10-01, 자체 로컬 실습의 입력값과 검사 시작 화면. 계정과 실제 개인정보를 사용하지 않았다.
판정: success가 표시된 실제 결과 화면
같은 세션에서 수정 예제를 적용하고 직접 검사한 결과: 판정: success.
실제 브라우저 버튼 조작과 결과 변화. 자체 실습이며 외부 제품 사용이나 서버 호출 영상이 아니다.

정책 함수를 실행하고 종료 조건을 검증하는 법

아래 함수에 상태 코드 배열을 넣으면 status, attempts, delays, trace가 반환됩니다. 처음부터 200이면 1회 성공, 500이 세 번이면 exhausted, 403이면 1회 중단이라는 결과를 각각 확인하세요. 시도 수와 대기 배열을 같이 보는 것이 중요합니다. 최대 세 번이라는 조건이 재시도를 세 번 더한다는 뜻으로 잘못 구현되기 쉽기 때문입니다.

실제 호출을 붙일 때는 재시도 루프 안에서 요청 본문과 대상 ID를 유지해야 합니다. 실패할 때마다 새 대상이나 새 문서를 만들면 같은 작업의 복구가 아니라 추가 작업이 됩니다. 오류를 사용자에게 보고할 때도 시도 수와 종료 이유를 같이 적으면 권한 확인이 필요한 문제와 나중에 다시 실행할 문제를 구분할 수 있습니다. 민감한 요청 본문이나 인증 헤더를 실행 기록에 넣지 않는 원칙도 필요합니다.

예를 들어 첫 응답을 잃은 글쓰기 작업은 다음 시도에서 같은 글의 존재를 먼저 조회해야 합니다. 반면 공개 문서 읽기는 동일 주소를 다시 요청해도 새 글이 생기지 않습니다. 이런 차이를 작업별 계약에 적고, 재시도 함수의 호출자는 읽기·쓰기 유형을 구분해야 합니다. 운영 기록에는 작업 이름, 시작 시각, 대상 지문, 최종 판정과 확인한 대상 ID를 남기면 다음 실행이 같은 상태를 이어받을 수 있습니다. 응답 본문을 모두 기록하는 것보다 복구에 필요한 최소 정보를 고르는 편이 자료 관리에도 도움이 됩니다.

const check = function(statuses) {
      const delays = [], trace = [];
      for (let i = 0; i < Math.min(3, statuses.length); i++) {
        const status = statuses[i]; trace.push(`시도 ${i + 1}: HTTP ${status}`);
        if (status >= 200 && status < 300) return { status: 'success', attempts: i + 1, delays, trace };
        if (status !== 429 && !(status >= 500 && status <= 599)) return { status: 'blocked', attempts: i + 1, delays, trace };
        if (i < 2 && i + 1 < statuses.length) delays.push(2 ** i);
      }
      return { status: 'exhausted', attempts: trace.length, delays, trace };
    };

console.log(check([403, 200]));
console.log(check([429, 500, 200]));
console.log(check([200]));
console.log(check([500, 500, 500]));
console.log(check([]));

한계와 실패 조건: 중복 쓰기는 별도 문제다

이 함수는 실제 fetch, 타임아웃 취소, 헤더 파싱과 동시 실행 잠금을 구현하지 않습니다. idempotency key나 서버 조회로 중복을 복구하는 기능도 없습니다. 안전한 읽기 요청과 외부 상태를 바꾸는 쓰기 요청에 동일한 정책을 무조건 적용하면 안 됩니다. 요청을 보낸 뒤 응답을 잃었을 때는 대상의 실제 상태를 확인하는 경로가 먼저 필요할 수 있습니다.

상태열이 비어 있으면 실행할 응답이 없으므로 exhausted와 시도 0을 반환합니다. 상태값이 정상적인 HTTP 코드인지 검사하는 기능도 이 예제에서는 호출자가 맡습니다. 서버의 정책이 409나 특정 4xx에 별도 재시도를 허용할 수 있지만 그 예외는 공식 계약을 확인한 뒤 추가하세요. AI가 코드를 만들어 줬다는 이유로 오류 목록을 넓히지 말고 새 분기에 대한 성공·실패 테스트를 함께 작성해야 합니다.

자동화 운영에 붙일 때 남길 체크리스트

최대 횟수는 몇 번이 적당한가요? 업무의 전체 제한 시간과 외부 변경 비용을 먼저 보고 정합니다. 여기의 세 번은 실습을 위한 상한이며 모든 서비스에 대한 정답이 아닙니다.

403이 나오면 다음 날 다시 실행해도 되나요? 권한이나 정책이 바뀌지 않으면 같은 문제가 반복될 수 있습니다. 차단 이유와 재검토 조건을 보존하고 조건이 달라질 때 확인하는 편이 유용합니다.

시간 초과면 새 작업을 만들면 되나요? 서버에 이미 반영됐을 가능성을 확인해야 합니다. 같은 대상 ID와 요청 지문으로 상태를 조회하고 복구할 수 있을 때 중복 생성보다 먼저 수행하세요. 이 확인 절차는 상태 코드 분기와 별개로 설계해야 합니다.

검수 사례 표

입력 조건 직접 검사할 기대 결과
403 → 200 1회 blocked, 두 번째 상태 미사용
429 → 500 → 200 3회 success, 대기 정책 1·2초
500 → 500 → 500 3회 exhausted
첫 200 1회 success

공식 출처와 함께 읽을 글

AI 프롬프트 회귀 테스트 실전에서는 입력을 고정하고 수정 전후 차이를 확인하는 다른 검수 과정을 살펴볼 수 있습니다.