CCAR-P 개념 카드

■ API 오류별 대응

500·529·429·504 · 지출 상한 429 · request-id7.3 본편

표시가 없는 문장은 공식 문서에서 확인한 내용이에요. 다른 표시는 읽는 법

왜 배우나 — 시험이 요구하는 것

시험 목표 7.3 디버깅과 운영 문제 해결 · D7 개발팀 7%
Support debugging and operational issue resolution

이 개념으로 푸는 판단 (할 수 있어야 하는 것)

  • 7.3③ API 오류가 쏟아질 때 무엇부터 보나? — 오류 종류별 대응 (재시도할 것 / 한도를 볼 것 / 오류가 아닌 것)

한눈에

API 오류는 HTTP 상태와 error.type(JSON)으로 온다. 할 일은 코드가 정한다

  • 500·529 : 일시 오류다. 지수 백오프로 재시도한다
  • 429 : 한도다(속도 또는 지출 상한)
  • 504 : 긴 요청은 스트리밍으로 보낸다
  • 400대 : 내 요청·키·권한을 고친다

모든 응답에 request-id 헤더가 붙는다(오류 본문에는 같은 값이 request_id 로 온다). 이 값이 문의·추적의 열쇠다. 거절은 오류가 아니다(HTTP 200). 자세한 것은 ■ stop_reason 으로 분기 에 있다

비유 5xx 는 백오프 재시도와 서킷 브레이커로, 429 는 스로틀·쿼터 확인으로, 4xx 는 클라이언트 버그 수정으로 다룬다. 추적은 X-Request-ID 로 게이트웨이·백엔드 로그를 잇는 것과 같다

API 오류는 상태 코드로 가른다. 500·529 는 백오프 재시도, 429 는 한도, 504 긴 요청은 스트리밍, 400대는 요청을 고치고, request-id 로 추적한다.
그림으로 보기 (AI 생성 · Codex · 누르면 크게)

ELI5

가게에 전화했는데 안 되는 이유가 여러 가지예요.

  • "지금 손님이 너무 많아요" → 조금 있다 다시 걸면 돼요 (500·529).
  • "오늘 주문 한도를 넘었어요" → 다시 걸어도 소용없을 때가 있어요 (429).
  • "주문서가 잘못 적혔어요" → 주문서를 고쳐야 해요 (400대).
  • 전화마다 붙는 접수 번호를 적어 두면, 나중에 가게에 물어볼 수 있어요 (request-id).

개념 설명

영상 — 밤마다 504, 어떻게 고칠까? (약 43초 · 소리 없음 · 자막). 밤 4번 · 타임아웃 깃발 자리 · 끊기는 자리는 그림용 가정 · 실측 아님 작은 화면에서는 전체화면(⛶)으로 보세요.

원리

오류는 "누구 문제인가"를 알려 준다

  • 5xx(500·529·504)는 Anthropic 쪽 또는 요청 처리 쪽의 일시 문제다. 같은 요청을 잠시 뒤 다시 보내면 대개 풀린다. 그래서 지수 백오프로 재시도한다.
  • 429 는 내 조직의 한도다. 아래 두 가지가 섞여 있다. 구분은 ■ rate limit 에 있다.
    • 기다리면 풀리는 것 : rate limit(속도 제한)이다. retry-after 가 있다
    • 기다려도 안 풀리는 것 : 티어 월 지출 상한이다. retry-after 가 없다
  • 400대는 내 요청 자체가 틀린 것이다. 몇 번을 다시 보내도 결과가 같다. 요청·키·권한을 고친다.
  • 504 는 요청이 너무 오래 걸린 것이다. 재시도보다 요청 방식을 바꾼다(스트리밍·배치).

오류가 아닌 실패가 있다

  • 거절은 HTTP 200 과 stop_reason: "refusal" 로 온다. 오류율 감시에 보이지 않는다.
  • 스트리밍은 200 을 먼저 보낸 뒤 중간에 error 이벤트가 올 수 있다. HTTP 상태만 보면 놓친다.

재시도는 이미 누가 하고 있다

  • 공식 SDK 는 일시 오류를 기본 2번 재시도한다. Claude Code 는 기본 10번 재시도하고, 포기한 뒤에야 api_error 를 1번 남긴다.
  • 그 위에 또 재시도를 감싸면 시도 수가 곱해진다. 그래서 한도와 비용을 더 먹는다(업계 일반).

추적은 request-id 로 한다

  • 모든 응답에 붙는다. 오류 본문에도 같은 값이 있다. 지원 문의와 로그 대조의 열쇠다.

핵심 질문은 두 개다

  • 이 실패는 기다리면 풀리나, 고쳐야 풀리나?
  • 내 감시가 이 실패를 볼 수 있나(200 인 실패 포함)?

규칙과 판단

공식 SDK 는 이미 기본 2번 재시도하고 Claude Code 는 재시도를 다 한 뒤 1번 기록한다. HTTP 200 이어도 거절이나 스트림 중간 오류는 따로 처리한다.
그림으로 보기 (AI 생성 · Codex · 누르면 크게)

갈림길

①② 상태 코드로 가르기 [7.3③]

상태 코드가 무엇인가?error.type 도 함께 본다
500 api_error

백오프 재시도

계속되면 request ID 와 함께 지원팀에 문의한다

529 overloaded_error

일시 과부하

내 한도 문제가 아니다. 백오프로 재시도한다

504 timeout_error

긴 요청

스트리밍 Messages API 나 Message Batches 를 쓴다

429 rate_limit_error

한도

rate limit 또는 지출 상한이다. 자세한 것은 ■ rate limit 에 있다

400 · 401 · 403 · 404 · 413

요청을 고친다

형식·키·권한·경로·크기를 고친다. SDK 가 자동 재시도하는 일시 오류(연결·429·5xx)가 아니다. 400 은 재시도해도 안 되는 오류다. 내가 건 지출 한도에 도달해도 400 이 온다. 그때는 한도를 올린다

200 인데 답이 이상하다

↓ 아래 「오류가 아닐 때」 갈림길로 이어짐

다음 물음 — 200 인데 무엇이 왔나?

④ 오류가 아닐 때 [7.3③] [4.6③]

200 인데 무엇이 왔나?
content 가 비어 있다 · refusal

거절

HTTP 200 과 stop_reason: "refusal" 이 온다. 자세한 것은 ■ stop_reason 으로 분기 에 있다

스트림 중간 error 이벤트

스트림 오류 처리

200 뒤 오류는 표준 오류 처리를 따르지 않는다. 오류 이벤트를 따로 처리한다

③⑤ 재시도는 누가 [7.3③]

어디서 부르나?
공식 SDK

이미 재시도한다

연결 오류·429·5xx 를 지수 백오프로 기본 2번 재시도한다. retry-after 를 따른다. max_retries 로 조정한다

Claude Code

포기한 뒤 1번 기록

api_error 는 재시도를 다 한 뒤 1번 남는다. attempt 11 은 일시 오류로 재시도를 소진했다는 뜻이다(기본 10번)

어디서든, 문의·추적할 때

request-id

모든 응답 헤더에 있다. 오류 본문에는 request_id 로 있다

흐름

그림 속 이름·금액·시간·토큰 수는 예시예요. 공식 한도·동작은 카드 본문 값이 기준.

장면 글로 보기

칸 : 앱 → SDK → API

규칙 (SDK) : 연결 오류·429·5xx 를 지수 백오프로 기본 2번 재시도한다

질문 : 이 오류, 다시 보내면 될까?

① 500 은 백오프 후 요청 ID 로 문의 ✓

  1. 시작 : 앱 — 쪽지 : POST /v1/messages
  2. 실패 : API → SDK : 500 api_error 가 온다 — 쪽지 : HTTP 500 / type: api_error / request_id: req_018…
  3. 재시도 : SDK → API : 지수 백오프로 기본 2번 재시도한다 — 쪽지 : 재시도 1/2 · 백오프 / 재시도 2/2 · 더 길게
  4. 문의 : SDK → 앱 : 계속되면 요청 ID 로 문의한다 — 쪽지 : 500 예외 · 재시도 소진 / request-id: req_018…
  5. 끝 : Anthropic 내부 오류다. 백오프로 재시도하고, 계속되면 요청 ID 로 문의한다

② 스트림 중간 오류 ≠

  1. 시작 : 앱 — 쪽지 : POST /v1/messages / stream: true
  2. 응답 : API → 앱 : HTTP 200 으로 스트림이 시작된다 — 쪽지 : HTTP 200 / 글자가 흘러옴…
  3. 오류 : API → 앱 : 스트림 중간에 오류 이벤트가 온다 — 쪽지 : event: error / type: overloaded_error
  4. 표시 : 앱 : 200 만 보고 성공으로 처리한다 — 쪽지 : 로그: 200 · 성공 / (답은 중간에 끊김)
  5. 끝 : 200 뒤 오류는 표준 오류 처리를 따르지 않는다. 오류 이벤트를 따로 처리해야 한다

③ 긴 요청 504 는 스트리밍으로 ✓

  1. 시작 : 앱 — 쪽지 : POST /v1/messages / max_tokens: 큰 값 / stream 없음
  2. 요청 : 앱 → API : 큰 max_tokens 를 비스트리밍으로 보낸다 — 쪽지 : 응답 기다리는 중… / (연결은 유휴)
  3. 끊김 : API : 유휴 연결이 끊긴다 — 쪽지 : HTTP 504 / type: timeout_error
  4. 바꿈 : 앱 → API : 스트리밍이나 Message Batches 로 바꾼다 — 쪽지 : stream: true / → 청크가 계속 옴
  5. 끝 : 긴 요청은 스트리밍으로 보낸다. 타임아웃 값만 늘리지 않는다

나머지 규칙

  1. 긴 요청 : 스트리밍·배치 없이 큰 max_tokens 를 쓰는 것은 피한다. 일부 네트워크가 유휴 연결을 끊어 응답 없이 실패하거나 시간이 초과된다. 배치는 결과를 폴링해 네트워크 위험을 덜어 준다. SDK 는 비스트리밍 요청이 10분 시간 초과를 넘을지 검증하고 TCP keep-alive 를 켠다 [7.3③]

규칙 원문 ①②③④⑤ (갈림길로 그린 규칙)
  1. 코드별 뜻과 할 일 (2026-09-28 조회) [7.3③]

    코드 type뜻할 일
    500 api_errorAnthropic 내부의 예기치 않은 오류지수 백오프로 재시도한다. 계속되면 request ID 와 함께 지원팀에 문의한다
    529 overloaded_errorAPI 일시 과부하백오프로 재시도한다 (내 한도 문제가 아니다. ■ rate limit)
    504 timeout_error처리 중 시간 초과긴 요청은 스트리밍 Messages API 로 보낸다
    429 rate_limit_errorrate limit · 티어 월 지출 상한 · Claude Code 워크스페이스 지출 한도지출 상한 429 는 retry-after 가 없고, 풀릴 때까지 계속 실패한다. 가르는 법은 ■ rate limit · 규칙 ⑤ 에 있다
    400 invalid_request_error요청 형식·내용 문제 · 내가 건 지출 한도 도달도 400요청을 고친다. 한도를 올린다
    401 · 403키 문제(형식·취소·만료) · 키에 그 리소스 권한이 없다키·워크스페이스 설정을 확인한다
    413 request_too_large크기 초과 (Messages 32 MB · Batch 256 MB)요청을 줄인다
    409 conflict_error리소스 현재 상태와 충돌충돌을 풀고 재시도한다
  2. 사용량이 갑자기 치솟으면 529 대신 429 가 날 수 있다. 이것이 가속 한도(acceleration limits)다 (2025-08-11 릴리스 노트) [7.3③]

    짧은 폭주는 ■ rate limit · 규칙 ① 에서 다룬다

  3. 재시도는 SDK 가 이미 한다 : 공식 SDK 는 연결 오류·rate limit(속도 제한)·5xx 를 지수 백오프로 기본 2번 재시도한다. retry-after 가 있으면 따른다. max_retries 로 조정하거나 끈다 [7.3③]

    오류는 SDK 의 타입 예외로 잡는다. 메시지 문자열로 매칭하지 않는다. 가장 구체적인 클래스부터 잡는다

    Claude Code 는 내부에서 재시도한다(CLAUDE_CODE_MAX_RETRIES 기본 10 · 상한 15). 포기한 뒤에만 claude_code.api_error 를 1번 남긴다

    attempt 11 은 일시 오류로 재시도를 소진했다는 뜻이다. 더 작으면 400 같은 재시도 안 되는 오류다. 회복 여부는 같은 session.id 에 뒤이은 api_request 가 있나로 본다 (2026-09-28 조회)

  4. 오류가 아닌 것 : 거절은 HTTP 200 과 stop_reason: "refusal" 로 온다. 그래서 오류 집계나 api_error 에 잡히지 않는다. Claude Code 는 claude_code.api_refusal 이벤트를 남긴다. 자세한 것은 ■ stop_reason 으로 분기 에 있다 [7.3③] [4.6③]

    스트리밍은 200 뒤에도 오류가 온다. event: error 안의 overloaded_error 는 비스트리밍의 529 에 해당한다. 표준 오류 처리를 따르지 않는다

  5. 추적 : 모든 응답에 request-id 헤더가 붙는다(예 req_018…). 오류 본문에는 같은 값이 request_id 로 온다 (2025-08-19~) [7.3③]

    Python·TypeScript SDK 는 _request_id 속성으로 읽는다. 다른 헤더는 with_raw_response 로 읽는다

    Claude Platform on AWS 는 ID 가 두 개다. x-amzn-requestid 는 CloudTrail 조회용이다. request-id 는 Anthropic 지원 티켓용이다

    Claude Code 텔레메트리의 request_id 도 같은 값이다. 타임아웃처럼 서버 ID 가 생기지 않은 실패는 client_request_id 를 쓴다

더 깊이 : 판단 규칙 · 상황 변수 (설명)

판단 규칙

조건답근거
500 api_error지수 백오프로 재시도한다. 계속되면 request ID 로 지원팀에 문의한다errors "Retry the request with exponential backoff; if the error persists, contact support with the request ID."
529 overloaded_error일시 과부하다. 백오프로 재시도한다errors (SDK 가 5xx 를 재시도)
504 timeout_error긴 요청은 스트리밍 Messages API 로 보낸다errors
429 · retry-after 가 없다 · enforced_spend_limit_reached티어 지출 상한이다. 재시도는 무의미하다. 상향을 요청한다errors · rate-limits
429 · retry-after 가 있다그 시간 뒤에 재시도한다(이르면 또 실패한다)rate-limits
400 · 내 지출 한도 도달400 으로 온다. 한도를 올린다errors
오류 처리 코드SDK 타입 예외를 구체적인 것부터 잡는다(문자열 매칭 X)errors
200 인데 빈 답이다거절이다. 오류가 아니다. 자세한 것은 ■ stop_reason 으로 분기 에 있다monitoring-usage
스트리밍 200 뒤 오류오류 이벤트를 따로 처리한다errors · streaming
문의·추적request-id 헤더와 본문 request_id 를 쓴다errors

상황 변수

변수값답 쪽등급근거
호출 경로공식 SDK일시 오류는 이미 2번 재시도한다. max_retries 로 조정한다errors
호출 경로Claude Code기본 10번 재시도 후 api_error 1건을 남긴다. 횟수는 attempt 로 본다monitoring-usage
호출 경로직접 HTTP백오프를 직접 짠다업계 일반—
사용량 모양갑자기 치솟는다529 대신 429(가속 한도)일 수 있다릴리스 노트 (2025-08-11)
사용량 모양월말에 누적된다지출 상한 429 가 나면 다음 달 1일 00:00 UTC 까지 멈춘다rate-limits
요청 길이큰 max_tokens · 비스트리밍스트리밍이나 배치를 쓴다errors
플랫폼Claude Platform on AWSID 가 두 개다. CloudTrail 은 x-amzn-requestid, 지원 티켓은 request-id 를 쓴다errors
응답 모양스트리밍HTTP 상태만으로는 부족하다errors

연습 문제

매일 밤 긴 월간 보고서를 만드는 앱이 큰 max_tokens 로 스트리밍 없이비스트리밍 요청을 보낸다. 요즘 HTTP 504 timeout_error504 로 자주 실패하자 개발자는 클라이언트 타임아웃 값을 더 늘리려 한다. 어떻게 고쳐야 하나?

시험 대비

함정

  • "피크에 실패가 급증하니 모델이 불안정하다. 모델을 바꾼다" 는 함정이다. 상태 코드부터 본다. 5xx·529 는 일시 오류(백오프)이고, 429 는 한도다. 모델 품질 문제가 아니다 업계 일반 단 한도는 모델마다 따로라 다른 모델을 섞으면 429 는 덜 수 있음 ■ rate limit · 규칙 ④
  • "429 면 즉시 무한 재시도한다" 는 함정이다. retry-after 보다 이르면 또 실패한다. 지출 상한 429 는 계속 실패한다
  • "500 이 계속돼도 재시도만 한다" 는 함정이다. 계속되면 request ID 로 문의한다
  • "504 면 타임아웃 값만 늘린다" 는 함정이다. 긴 요청은 스트리밍으로 보낸다
  • "오류율 대시보드가 조용하니 정상이다" 는 함정이다. 거절은 200 으로 온다. 스트림 중간 오류는 200 뒤에 온다
  • "오류 메시지 문자열로 분기한다" 는 함정이다. SDK 타입 예외를 구체적인 것부터 잡는다
  • "Claude Code api_error 1건은 한 번 실패다" 는 함정이다. 재시도를 다 한 뒤 1번 남는다. 횟수는 attempt 로 본다
  • "SDK 위에 재시도 루프를 또 감싼다" 는 함정이다. SDK 가 이미 2번 재시도한다. 겹치면 시도 수가 곱해진다 업계 일반
  • "400 이니 한도는 아니다" 는 함정이다. 내가 건 지출 한도에 도달해도 400 이 온다

신호

"Retry the request with exponential backoff; if the error persists, contact support with the request ID."

"A tier spend-cap 429 has no retry-after header and keeps failing until access resumes"

"The official SDKs automatically retry transient failures (such as connection errors, rate limits, and 5xx server errors) with exponential backoff, twice by default, honoring the retry-after header when present."

"Consider using the streaming Messages API for long-running requests."

"an error can occur after the API returns a 200 response."

"Every API response includes a unique request-id header."

"Catch the SDK's typed classes rather than string-matching error messages, handling the most specific classes first."

"Refusals arrive on a successful response stream rather than as an HTTP error, so the api_error event doesn’t fire for them."

"Previously, 529 (overloaded_error) errors would occur in similar scenarios." (릴리스 노트 2025-08-11)

보통은 상태 코드부터 보고 모델을 바꾸지 않지만, 429 가 한 모델에 몰리거나 refusal 이면 다른 모델로, 안 풀리는 429 는 지출 상한이라 상향을 요청한다.
그림으로 보기 (AI 생성 · Codex · 누르면 크게) — 자세한 조건은 아래 '더 깊이'에 있어요
더 깊이 : 뒤집히는 때 · 오답 재료 (설명)

뒤집히는 때

1. 모델을 바꾸는 게 맞는 때

  • 조건 : 오류가 한 모델의 429 에 몰려 있다. 또는 200 인데 refusal 로 빈 답이 온다.
  • 판단 : "모델 교체 = 엉뚱한 계층" 은 5xx·529 일 때 이야기다. rate limit 은 모델마다 따로다. 그래서 다른 모델을 섞으면 그 모델의 한도까지 더 쓴다(■ rate limit · 규칙 ④). 거절은 같은 모델에 다시 보내면 대개 또 거절된다. 그래서 다른 모델로 보낸다(■ stop_reason 으로 분기 · 규칙 ③).
  • 근거 : rate-limits 카드 ④ · stop-reason 카드 ③
  • 그래도 첫 수는 상태 코드와 stop_reason 확인이다. 그것을 안 보고 "불안정하니 교체" 하는 보기는 오답 쪽이다.

2. 재시도를 겹쳐 감쌌을 때

  • 조건 : 앱이 SDK 호출을 자체 재시도 4번으로 감쌌다. SDK 는 기본 2번 재시도한다.
  • 계산 : 앱 1회 호출에 SDK 가 최대 3번 시도한다(1 + 2). 앱은 최대 5번 호출한다(1 + 4). 그래서 요청 하나가 최대 15번 API 를 두드린다.
  • 판단 : 과부하·rate limit 상황에서 시도가 곱해지면 회복이 늦어진다. SDK 의 max_retries 를 조정하거나 겹친 재시도를 걷어 낸다.
  • 등급 : 계산 (SDK 기본 2번은 확인이다. "회복이 늦어진다" 는 업계 일반이다)
  • 근거 : errors

3. Claude Code 의 api_error 1건

  • 조건 : 텔레메트리에 claude_code.api_error 가 1건 있다. attempt 는 11 이다.
  • 판단 : 1번 실패가 아니다. 일시 오류로 11번(첫 시도 + 기본 10번 재시도) 다 해 보고 포기한 것이다. attempt 가 1~2 처럼 작으면 원인은 둘 중 하나다. 400 같은 재시도 안 되는 오류이거나, 자체 재시도 예산이 작은 원인이다(예 AWS·Google Cloud 자격증명 로드 실패는 최대 2번).
  • 회복 여부 : 같은 session.id 에서 그 오류 뒤에 api_request 가 이어지나로 본다.
  • 근거 : monitoring-usage

4. 429 인데 기다려도 안 풀리는 때

  • 조건 : 월 중순부터 모든 요청이 429 다. 헤더에 retry-after 가 없다.
  • 판단 : rate limit 이 아니라 티어 월 지출 상한이다. error.details.error_code 는 enforced_spend_limit_reached 다. SDK 재시도도 계속 실패한다. 그래서 상향을 요청한다.
  • 근거 : errors · rate-limits

오답 재료

오답왜 끌리나왜 틀리나등급근거
"피크에 실패가 급증하니 모델이 불안정, 모델 교체"실패가 모델 호출에서 나니 모델 탓 같다상태 코드부터 본다. 5xx·529 는 일시 오류, 429 는 한도다. 엉뚱한 계층을 고치는 것이다 (단 뒤집히는 때 1)업계 일반 + 확인errors
"429 에 즉시·무한 재시도"재시도가 기본 대응 같다retry-after 보다 이르면 또 실패한다. 지출 상한 429 는 계속 실패한다rate-limits · errors
"500 이 계속돼도 재시도 횟수만 늘린다"언젠간 될 것 같다계속되면 request ID 로 문의한다errors
"504 면 타임아웃 값만 늘린다"설정 한 줄로 끝난다긴 요청은 스트리밍·배치로 보낸다. 네트워크가 유휴 연결을 끊는다errors
"오류율(5xx) 대시보드가 조용하니 정상"오류가 없어 보인다거절은 200 이다. 스트림 중간 오류는 200 뒤에 온다monitoring-usage · errors
"오류 메시지 문자열로 분기"메시지에 이유가 적혀 있다SDK 타입 예외를 구체적인 것부터 잡는다. type 값은 늘어날 수 있다errors
"400 이니 한도 문제는 아니다"한도 = 429 로 외웠다내가 건 지출 한도 도달은 400 이다errors
"SDK 위에 재시도 루프를 또 감싸 안정성 확보"겹겹이 방어 같다SDK 가 이미 2번 재시도한다. 겹치면 시도 수가 곱해진다계산뒤집히는 때 2

참고

더 깊이 : 출처 · 상태 · 미해결 (참고)

출처

상태

  • 업계 일반 2줄

미해결

  1. 목록 7.3③ 의 "529 overloaded = 일시 과부하" 뒤 처방 : errors 문서의 529 줄에는 처방 문장이 없다. "백오프 재시도" 는 SDK 가 5xx 를 재시도한다는 17줄과 ■ rate limit 카드에서 가져왔다.
  2. 가속 한도(acceleration limits)는 2025-08-11 릴리스 노트에만 있다. 지금 rate-limits 문서에는 이 단어가 없다(검색어 acceleration). 지금 문서의 가까운 문장은 "Short bursts of requests can exceed the limit" 다(■ rate limit).
  3. 408·409 를 SDK 가 자동 재시도하는지는 확인하지 못했다. errors 문서는 "such as connection errors, rate limits, and 5xx" 예시만 든다. 409 는 "충돌을 풀고 재시도" 만 확인했다.
  4. 목록의 영어 신호 두 개(500 줄 · 지출 상한 429 줄)는 원문에서 찾았다. 목록 그대로다 ✓. 목록의 "Claude Code 감시도 api_error 가 아니라 api_refusal" 도 monitoring-usage에서 확인했다 ✓.