OpenAI API 429 slow_down 대응법: 재시도 로직을 에러 코드 기준으로 나눠야 하는 이유
검색 의도: OpenAI API 429 slow_down, OpenAI API 503 server_is_overloaded, Retry-After 재시도 로직, AI API rate limit 운영
OpenAI가 2026년 9월 2일 API 에러 응답을 바꿨다. 이제 트래픽이 너무 빠르게 증가한 상황은 429와 slow_down 코드로, 일시적인 모델 과부하는 503과 server_is_overloaded 코드로 구분된다. 둘 다 Retry-After 헤더를 줄 수 있고, 헤더가 있으면 최소 그 시간만큼 기다린 뒤 재시도해야 한다. 헤더가 없으면 exponential backoff를 쓰는 것이 기본이다.
겉으로 보면 작은 에러 코드 변경이다. 하지만 프로덕션에서 OpenAI API를 쓰는 팀에는 꽤 큰 운영 신호다. 지금까지 많은 서비스가 429를 전부 rate limit으로, 5xx를 전부 장애로 뭉뚱그려 처리했다. 그 결과 실제 원인이 “우리 트래픽 램프업이 너무 공격적”인지, “모델 서버가 일시적으로 바쁜 것”인지 구분하지 못했다. 이번 변경은 재시도 정책, 큐 설계, 알림 기준, 대시보드 라벨을 나눠야 한다는 뜻이다.
왜 429와 503을 나눠야 하나
429 slow_down은 대체로 클라이언트 쪽 제어 문제다. 짧은 시간에 요청량을 갑자기 올렸거나, 신규 배포 후 워커 수가 한꺼번에 늘었거나, 배치 작업이 평소보다 큰 입력을 밀어 넣었을 때 발생한다. 이 경우 같은 속도로 재시도하면 상황이 더 나빠진다. 재시도 요청이 원래 요청보다 더 많은 부하를 만들기 때문이다.
반대로 503 server_is_overloaded는 공급자 쪽 일시 과부하 신호다. 이때도 무작정 재시도하면 안 되지만, 운영 판단은 다르다. 429가 늘면 내부 throttle, queue depth, rollout speed를 먼저 봐야 한다. 503이 늘면 provider status, model fallback, degraded mode를 봐야 한다. 같은 “실패”라도 책임 경계와 조치가 달라진다.
실무에서 중요한 차이는 알림 문구다. 429 slow_down 알림은 “요청 증가율을 낮추라”에 가깝다. 503 server_is_overloaded 알림은 “fallback을 켜거나 지연을 허용하라”에 가깝다. 이 둘을 같은 PagerDuty 이벤트로 보내면 담당자가 매번 로그를 뒤져야 한다.
Retry-After를 먼저 믿고, 없을 때만 backoff를 쓴다
재시도 로직에서 가장 흔한 실수는 모든 실패에 동일한 sleep을 적용하는 것이다. OpenAI가 Retry-After를 명시할 수 있다고 했으니, 우선순위는 분명하다. 응답 헤더에 값이 있으면 그 값이 1순위다. 그 시간보다 빨리 재시도하면 서버가 준 혼잡 제어 신호를 무시하는 셈이다.
헤더가 없을 때는 exponential backoff와 jitter를 같이 써야 한다. 예를 들어 1초, 2초, 4초, 8초처럼 늘리되, 모든 워커가 같은 시점에 다시 몰리지 않도록 2040% 범위의 랜덤 지연을 더한다. 최대 재시도 횟수도 필요하다. 사용자 요청이면 23회 이후 “잠시 후 다시 시도”로 돌려보내는 편이 낫다. 백그라운드 작업이면 큐에 다시 넣고 다음 스케줄에서 처리할 수 있다.
간단한 기준은 이렇다. 온라인 요청은 사용자 경험을 보호하고, 배치 요청은 전체 완료율을 보호한다. 온라인 요청에 긴 재시도를 붙이면 화면이 멈춘다. 배치 요청에 짧은 재시도만 붙이면 실패율이 올라간다. 같은 API라도 호출 맥락별로 정책을 나눠야 한다.
큐와 워커 수를 같이 조정해야 한다
slow_down은 단순히 sleep만 넣는다고 해결되지 않는다. 워커가 100개이고 각 워커가 실패 후 5초 뒤 다시 요청하면, 5초마다 큰 파도가 반복된다. 큐 기반 구조라면 global concurrency limit을 둬야 한다. 특정 모델 또는 프로젝트 단위로 동시에 보낼 수 있는 요청 수를 제한하고, 실패율이 올라가면 자동으로 워커 수를 낮춘다.
예를 들어 문서 요약 배치가 10,000건 있다고 하자. 평소에는 동시 50개 요청으로 잘 돌지만, 신규 데이터가 들어온 날 동시 200개로 올리면 429 slow_down이 늘 수 있다. 이때 필요한 것은 “재시도 3회”가 아니라 “동시성 50으로 되돌리고 큐 지연을 허용”하는 결정이다.
서비스별로 중요도도 다르다. 결제 직후 생성되는 핵심 결과물은 우선순위를 높이고, 내부 리포트나 추천 캐시 갱신은 낮춰도 된다. rate limit 대응을 제대로 하려면 모든 요청을 같은 줄에 세우지 말고, priority queue를 둬야 한다.
모델 fallback은 503에서 더 의미가 있다
503 server_is_overloaded가 늘 때는 fallback 전략을 검토할 수 있다. 같은 작업을 더 작은 모델로 처리해도 되는지, 답변 품질을 낮춰도 되는지, 실시간 응답 대신 비동기로 넘겨도 되는지를 미리 정해야 한다. 다만 fallback은 만능이 아니다. 모델이 바뀌면 응답 형식, 안전성, 비용, latency가 모두 바뀐다.
구조화 출력이 필요한 API라면 fallback 모델에서도 schema 검증을 반드시 통과시켜야 한다. 요약이나 분류처럼 비교적 관대한 작업은 fallback이 쉽다. 코드 생성, 법률·의료·금융 판단처럼 정확도 민감도가 높은 작업은 fallback보다 지연 안내가 낫다.
운영 문서에는 “어떤 에러에서 어떤 fallback을 허용하는지”를 표로 남겨야 한다. 사람이 장애 중에 새로 판단하게 만들면 실수한다.
대시보드에는 에러 코드보다 조치 기준을 보여줘야 한다
모니터링에서 429와 503 숫자만 보여주면 부족하다. 개발자가 필요한 것은 다음 액션이다. slow_down 비율, 평균 Retry-After, 재시도 후 성공률, 큐 대기 시간, 모델별 실패율, 요청량 증가율을 같이 봐야 한다. 특히 요청량 증가율은 slow_down을 설명하는 핵심 지표다.
알림 기준도 분리한다. 429 slow_down이 5분 동안 3%를 넘으면 신규 워커 증가를 멈추고 동시성을 낮춘다. 503 server_is_overloaded가 5분 동안 3%를 넘으면 fallback 후보를 켜거나 비동기 처리로 전환한다. 숫자는 서비스마다 다르지만, “에러가 났다”가 아니라 “어떤 레버를 당길지”가 알림에 들어가야 한다.
실행 체크리스트
- OpenAI API 에러 파서를 수정해
status,code,Retry-After를 모두 저장한다. 429 slow_down과503 server_is_overloaded를 별도 metric label로 분리한다.Retry-After가 있으면 우선 적용하고, 없을 때만 exponential backoff와 jitter를 사용한다.- 온라인 요청과 배치 요청의 최대 재시도 횟수, timeout, 사용자 메시지를 다르게 둔다.
- 모델별 global concurrency limit을 두고
slow_down증가 시 자동으로 낮춘다. - priority queue로 결제 직후 작업, 사용자 대기 작업, 내부 배치 작업을 분리한다.
503대응용 fallback 모델과 degraded mode를 사전에 문서화한다.- 대시보드에 재시도 후 성공률, 큐 지연, 요청량 증가율을 함께 표시한다.
이번 변경의 핵심은 “OpenAI API가 실패했다”를 더 잘 말할 수 있게 됐다는 점이다. 에러 구분이 선명해졌다면 클라이언트도 선명해져야 한다. 재시도는 운에 맡기는 반복이 아니라 혼잡 제어 프로토콜이어야 한다.