AI 예산 소진을 풀스택 API 계약으로 만들기
요약
OpenAI의 지출 한도 설정에 대응하여, API 예산 소진 문제를 풀스택 엔드투엔드 계약으로 처리하는 설계 방법을 제안합니다. 에러 정규화, 멱등성 보장, 상태 영속화를 통해 UI 루프를 방지하고 안정적인 시스템을 구축하는 가이드를 제공합니다.
핵심 포인트
- 제공자의 에러를 정규화하여 타입화된 AiFailure 객체로 관리
- 멱등성 키를 사용하여 API 호출 전 상태를 영속화하고 큐에 저장
- 예산 소진 시 409 에러와 함께 명확한 상태를 반환하여 UI 루프 방지
- 조건부 쓰기를 통해 데이터 덮어쓰기를 방지하고 안정성 확보
브라우저가 요약 작업을 제출하고, 워커(worker)가 하드 지출 임계값(hard spend threshold)에 도달한 후 제공자(provider)에게 도달하면 API 호출이 실패합니다. 만약 모든 계층이 이를 일반적인 500 에러로 변환한다면, UI는 루프를 생성할 수 있는 재시도 버튼을 제공하게 됩니다. 예산 소진은 단순히 결제 대시보드만 필요한 것이 아니라, 타입이 지정된 엔드투엔드(end-to-end) 계약이 필요합니다.
OpenAI의 7월 20일 릴리스 노트는 조직(organization) 및 프로젝트 지출 한도를 추가했으며, 하드 한도(hard limits)로 인해 임계값 이후 API 응답이 실패할 수 있다고 명시하고 있습니다. 해당 제품 및 계정에 대해 문서화된 대로 가용성(availability)을 처리하십시오. 이것은 7월 27일에 발표된 뉴스가 아니라, 이 동작에 대해 확인된 최신 공식 신호입니다. 검증되지 않은 7월 27일의 2차 보도 내용은 제외했습니다.
제공자 경계(provider seam) 정의
애플리케이션을 통해 제공자의 텍스트를 그대로 노출하지 마십시오. 증거를 통해 분류할 수 있는 에러만 정규화(normalize)하십시오:
type AiFailure =
| { kind: "budget_exhausted"; retryable: false; scope: "project" | "organization" | "unknown" }
| { kind: "rate_limited"; retryable: true; retryAfterMs?: number }
...
SDK의 현재 구조화된 상태/코드가 해당 분류를 지원할 때만 budget_exhausted를 매핑하십시오. 추측에 기반한 문자열 매칭은 권한 부여(authorization) 또는 장애(outage) 실패를 잘못 분류할 수 있습니다. 알 수 없는(Unknown) 상태는 알 수 없는 상태로 남겨두고 소유자에게 페이지(page)를 보냅니다.
호출 전 영속화(Persist)
POST /api/summaries는 멱등성 키(idempotency key)를 수락해야 하며, {"status":"queued","id":"job_91"}를 영속화(persist)한 다음 작업을 큐에 넣어야 합니다.
워커(Worker) 의사코드(pseudocode):
async function execute(job: StoredJob) {
if (job.status !== "queued") return;
try {
...
조건부 쓰기(Conditional writes)는 늦은 덮어쓰기를 방지하며, 공개 기록(public records)에서는 비밀(secrets)과 민감한 응답을 제외합니다.
브라우저 동작
지속 가능한 상태(durable state)를 폴링(poll)하거나 스트리밍(stream)하십시오. 예산 소진의 경우, 안정적인 애플리케이션 응답을 반환하십시오:
type이 ai-budget-exhausted이고, job ID, canRetry:false, 그리고 애플리케이션에서 추정한 재시도 시간이 명확하게 표시된 409 application/problem+json을 반환하십시오. 입력을 보존하고, 즉각적인 재시도를 비활성화하며, 취소 옵션을 제공하고, 한도 결정은 권한이 있는 운영자에게 맡기십시오.
계층 간 테스트 매트릭스 (Cross-layer test matrix)
| 케이스 (Case) | 제공자 경계 (Provider seam) | 저장된 상태 (Stored state) | HTTP/UI | 예상 호출 (Expected calls) |
|---|---|---|---|---|
| 정상 (normal) | 결과 (result) | 완료 (complete) | 요약 렌더링 (render summary) | 1 |
| ... |
정상 경로 (Normal path): 하나의 멱등성 제출 (idempotent submission)이 하나의 작업 (job)을 생성하고, 하나의 제공자 호출이 성공하며, 영속성 (persistence)이 결과를 커밋하고, 새로고침 (refresh)이 동일한 완료된 표현을 읽습니다.
실패 경로 (Failure path): 분류 (classification) 단계에서 지원되는 예산 증거를 감지하면, 워커 (worker)가 원자적으로 blocked_budget을 표시하고, UI는 재시도를 억제합니다. 만약 분류가 불확실하다면 작업은 failed 상태가 됩니다. 추측을 바탕으로 사용자에게 결제 수단 변경을 요구하지 마십시오.
재개 (Resume)는 비교 후 설정 (compare-and-set), 운영자 감사 (operator audit), 그리고 원래의 멱등성 키 (idempotency key)를 사용합니다. 램프업 (Ramp)은 배치 (batches) 단위로 점진적으로 진행합니다.
인도 체크리스트 (Delivery checklist)
- 조직/프로젝트 선택 기능을 서버 소유 설정 (server-owned configuration)에 배치하십시오.
- 외부 작업 전에 작업 정체성 (operation identity)과 입력 수정 사항 (input revision)을 영속화하십시오.
- 피스처 테스트 (fixture tests)를 통해 현재의 구조화된 제공자 오류 (structured provider errors)를 분류하십시오.
- 자동 재시도 계층 (automated retry layer)에서 예산 소진이 재시도 불가능하도록 만드십시오.
- 재개 (resume)와 취소 (cancellation)를 독립적으로 권한 부여하십시오.
- 중복 제출, 지연된 응답, 복구된 예산, 그리고 알 수 없는 오류를 테스트하십시오.
- 작업 기록은 유지하면서 새로운 AI 수용 (AI admissions)을 비활성화하여 롤백 (Roll back)하십시오.
이 방식은 임계값 호출, 리셋 또는 가용성을 예측할 수 없으며, 알림이나 재무 통제 (financial controls)를 대체하지 않습니다. SDK 버전을 고정하고 테스트하십시오.
별도의 MonkeyCode 실험
이후의 플랫폼 테스트에는 현재 해외 온라인 옵션을 갖춘 오픈 소스 AGPL-3.0 AI 개발 플랫폼으로 설명되는 MonkeyCode가 포함될 수 있습니다. 이는 관리형 서버 측 클라우드 개발 환경 (managed server-side cloud development environments), 모델/태스크/요구사항 관리 (model/task/requirement management), 그리고 빌드/테스트/미리보기 (build/test/preview) 기능을 제공합니다. 시작은 무료이지만, 저는 이 계약을 MonkeyCode에 대해 테스트하지 않았으며 동일한 오류가 발생한다는 주장도 하지 않습니다. 제공자의 이음새 (provider seam)와 실패 고정 장치 (failure fixtures)를 온전하게 유지한 후에만 공식 캠페인 페이지를 사용하십시오.
공개 사항: 이 기사는 공식 캠페인 링크를 사용하여 MonkeyCode를 홍보합니다. 저는 MonkeyCode 사용자이며 프로젝트와 관련이 없으며, 이 링크를 통해 어떠한 수수료도 받지 않습니다.
AI 지원 공개: 이 기사는 AI의 지원을 받아 초안이 작성되었으며, 인용된 1차 자료를 바탕으로 검토되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기