🔥 고급2026-04-179분
Batch API 50% 할인으로 대량 처리 파이프라인 만들기
임베딩 갱신, 로그 분류, 대량 요약 — 실시간이 아니면 Batch로 반값. 실전 워크플로우.
apibatch비용최적화
Batch API 기본
- 입력: 최대 10,000개 요청을 한 파일로 업로드
- 처리: Anthropic이 최대 24시간 내 완료 (보통 수 분~수 시간)
- 가격: 표준 대비 50% 할인 (Opus/Sonnet/Haiku 공통)
- 결과: 완료되면 JSONL 파일로 다운로드
언제 Batch인가
✅ 맞는 케이스
- 야간에 도는 이벤트 요약
- RSS/뉴스 대량 태깅
- 로그에서 PII 추출
- 임베딩 재생성
- 백필(backfill) 작업
❌ 안 맞는 케이스
- 챗봇 응답
- 사용자가 결과를 기다림
- tool use 루프 필요
코드: 제출
import Anthropic from "@anthropic-ai/sdk"
const client = new Anthropic()
const requests = docs.map((d, i) => ({
custom_id: `doc-${i}`,
params: {
model: "claude-haiku-4-5",
max_tokens: 200,
messages: [{
role: "user",
content: `다음을 한 문장으로 요약:\n\n${d.text}`,
}],
},
}))
const batch = await client.messages.batches.create({ requests })
console.log("batch id:", batch.id, "status:", batch.processing_status)
코드: 폴링 + 결과 수집
async function waitAndFetch(batchId: string) {
// 폴링
let b = await client.messages.batches.retrieve(batchId)
while (b.processing_status !== "ended") {
await new Promise(r => setTimeout(r, 30_000))
b = await client.messages.batches.retrieve(batchId)
console.log("progress:", b.request_counts)
}
// 결과 스트림
const results = await client.messages.batches.results(batchId)
const out: Record<string, string> = {}
for await (const r of results) {
if (r.result.type === "succeeded") {
const text = (r.result.message.content[0] as any).text
out[r.custom_id] = text
} else {
console.error("failed", r.custom_id, r.result)
}
}
return out
}
운영 패턴
1. 파티셔닝
10,000개 넘으면 여러 배치로 분할. 배치별 custom_id 네임스페이스 분리 (batch1-doc-0, batch2-doc-0).
2. 재처리
실패 요청만 골라 새 배치 제출. result.type === "errored" 필터링.
3. 멱등성
custom_id를 도메인 ID로 쓰면 결과 저장 시 upsert 가능 (중복 실행 안전).
4. 관측
- 제출 시점·완료 시점·성공률 기록
- 월별 Batch vs 일반 API 비용 비율 대시보드
트레이드오프
| 축 | Batch | 실시간 | |----|-------|-------| | 비용 | 50% 할인 | 정가 | | 지연 | 분~시간 | 초 | | tool use | 미지원 | 지원 | | 재시도 | 배치 레벨 | 요청 레벨 |
체크리스트
- [ ] 실시간 필요 없는 워크로드 식별
- [ ] custom_id에 도메인 식별자 쓰기
- [ ] 실패 요청 재배치 파이프라인
- [ ] 비용 집계 분리