Claude Batch API 가이드: 대량 처리로 비용 50% 절감하기
Claude Batch API는 실시간 API 대비 50% 저렴한 단가로 최대 10,000건의 요청을 비동기 일괄 처리한다. 결과는 24시간 이내(대부분 수 분~수 시간)에 JSONL 파일로 제공된다. 즉각적인 응답이 필요 없는 작업 — 콘텐츠 분류, 번역, 데이터 정제, SEO 메타 생성 — 에서 비용을 절반으로 줄이는 가장 직접적인 방법이다. Python SDK 한 줄로 배치를 생성하고, 폴링으로 완료를 확인하며, 스트리밍 JSONL로 결과를 소비한다.
언제 Batch API를 써야 하나?
Batch API와 실시간 API의 선택 기준은 단순하다. 응답 지연을 사용자가 체감하는 작업이면 실시간, 그렇지 않으면 배치다.
| 구분 | 실시간 API | Batch API |
|---|---|---|
| 응답 시간 | 수 초 이내 | 수 분~24시간 |
| 비용 | 기준 단가 | 기준 단가의 50% |
| 최대 요청 수 | 제한 없음 (Rate Limit 범위) | 배치당 10,000건 |
| 적합한 작업 | 챗봇, 실시간 번역, API 응답 | 배치 분류, 일괄 번역, 야간 파이프라인 |
Batch API가 유리한 대표 시나리오:
- 상품 리뷰 10,000건 감성 분석
- 블로그 글 500편 SEO 메타 디스크립션 일괄 생성
- 고객 지원 티켓 분류 및 우선순위 태깅
- 다국어 번역 파이프라인 (한→영, 한→일 등)
- 데이터셋 레이블링 및 정제
반면 사용자가 텍스트 입력 후 즉시 응답을 기다리는 챗봇이나, 실시간 스트리밍이 필요한 인터페이스에서는 실시간 API를 유지해야 한다.
Python 코드 예시
1. 배치 생성
import anthropic
client = anthropic.Anthropic()
# 처리할 요청 목록 구성
requests = []
texts = [
"이 제품은 정말 훌륭합니다. 배송도 빠르고 품질도 최고예요.",
"기대했던 것과 달랐습니다. 색상이 사진과 많이 달라요.",
"보통이에요. 가격 대비 나쁘지 않은 것 같습니다.",
# ... 최대 10,000건까지 추가 가능
]
for i, text in enumerate(texts):
requests.append(
anthropic.types.beta.messages.MessageCreateParamsNonStreaming(
model="claude-haiku-4-5",
max_tokens=100,
messages=[
{
"role": "user",
"content": f"다음 리뷰의 감성을 '긍정', '부정', '중립' 중 하나로만 답하세요.\n\n리뷰: {text}"
}
]
)
)
# 배치 생성
batch = client.beta.messages.batches.create(requests=requests)
print(f"배치 ID: {batch.id}")
print(f"상태: {batch.processing_status}")
# 출력 예: 배치 ID: batch_01ABC123...
# 상태: in_progress
2. 완료 대기 (폴링)
import time
def wait_for_batch(client, batch_id: str, poll_interval: int = 30):
"""배치 완료까지 폴링하며 대기."""
while True:
batch = client.beta.messages.batches.retrieve(batch_id)
status = batch.processing_status
if status == "ended":
print(f"완료! 성공: {batch.request_counts.succeeded}건, "
f"실패: {batch.request_counts.errored}건")
return batch
elif status == "canceling":
print("배치가 취소 중입니다.")
return None
print(f"처리 중... ({batch.request_counts.processing}건 남음)")
time.sleep(poll_interval)
# 폴링 실행 (30초 간격 권장)
completed_batch = wait_for_batch(client, batch.id)
3. 결과 처리 (JSONL 스트리밍)
results = {}
# 결과 스트리밍 — 메모리 효율적으로 한 줄씩 처리
for result in client.beta.messages.batches.results(completed_batch.id):
custom_id = result.custom_id
if result.result.type == "succeeded":
text = result.result.message.content[0].text
results[custom_id] = text
elif result.result.type == "errored":
error = result.result.error
print(f"요청 {custom_id} 실패: {error.type} — {error.message}")
# 결과 출력
for req_id, sentiment in results.items():
print(f"{req_id}: {sentiment.strip()}")
4. 전체 파이프라인 (프로덕션 패턴)
import anthropic
import json
import time
from pathlib import Path
def run_sentiment_batch(texts: list[str], output_path: str = "results.jsonl"):
client = anthropic.Anthropic()
# 요청 구성 (custom_id로 추적)
requests = [
anthropic.types.beta.messages.MessageCreateParamsNonStreaming(
custom_id=f"req_{i}",
model="claude-haiku-4-5",
max_tokens=50,
messages=[{
"role": "user",
"content": f"감성 분석 (긍정/부정/중립만 답할 것):\n{text}"
}]
)
for i, text in enumerate(texts)
]
# 배치 제출
batch = client.beta.messages.batches.create(requests=requests)
print(f"배치 제출 완료: {batch.id} ({len(requests)}건)")
# 완료 대기
while True:
batch = client.beta.messages.batches.retrieve(batch.id)
if batch.processing_status == "ended":
break
time.sleep(60)
# 결과 저장
with open(output_path, "w", encoding="utf-8") as f:
for result in client.beta.messages.batches.results(batch.id):
f.write(json.dumps({
"id": result.custom_id,
"sentiment": result.result.message.content[0].text.strip()
if result.result.type == "succeeded" else "ERROR"
}, ensure_ascii=False) + "\n")
print(f"결과 저장 완료: {output_path}")
return output_path
비용 계산 예시 (10,000건 기준)
Claude Haiku 기준으로 리뷰 감성 분석 10,000건을 처리하는 비용을 비교한다.
요청 구조 가정
- 시스템 프롬프트: 50토큰
- 사용자 메시지(리뷰 텍스트 + 지시): 평균 200토큰
- 응답(긍정/부정/중립): 평균 5토큰
입력 토큰 합계: (50 + 200) × 10,000 = 2,500,000 토큰
출력 토큰 합계: 5 × 10,000 = 50,000 토큰
실시간 API vs Batch API
| 구분 | 실시간 API | Batch API | 절감액 |
|---|---|---|---|
| 입력 단가 (Haiku) | $1.00 / 1M | $0.50 / 1M | — |
| 출력 단가 (Haiku) | $4.00 / 1M | $2.00 / 1M | — |
| 입력 비용 | $2.00 | $1.00 | -$1.00 |
| 출력 비용 | $0.20 | $0.10 | -$0.10 |
| 총합 | $2.20 | $1.10 | $1.10 (50%) |
| 원화 환산 | 약 3,080원 | 약 1,540원 | 약 1,540원 |
10,000건에서 $1.10 절감은 작아 보이지만, 동일 파이프라인을 매일 실행하면 월 $33(약 46,200원) 이 절약된다.
Sonnet으로 더 복잡한 작업(입력 평균 1,000토큰, 출력 500토큰, 10,000건)을 처리하는 경우:
| 구분 | 실시간 | Batch |
|---|---|---|
| 입력 비용 ($3.00/$1.50 per 1M) | $30.00 | $15.00 |
| 출력 비용 ($15.00/$7.50 per 1M) | $75.00 | $37.50 |
| 총합 | $105.00 | $52.50 |
Sonnet 수준 작업에서 10,000건당 $52.50 절감이 발생한다. 월 1회 실행만 해도 연간 $630(약 882,000원)을 아낄 수 있다.
자세한 비용 시뮬레이션은 Claude API 비용 계산 가이드에서 확인할 수 있다.
실전 사용 패턴
패턴 1: 콘텐츠 분류 파이프라인
블로그 운영자나 미디어 팀에서 수백~수천 편의 기사를 카테고리별로 자동 분류할 때 유용하다.
# 기사 제목 + 본문 첫 단락으로 카테고리 분류
def classify_articles(articles: list[dict]) -> list[dict]:
requests = [
anthropic.types.beta.messages.MessageCreateParamsNonStreaming(
custom_id=str(article["id"]),
model="claude-haiku-4-5",
max_tokens=30,
messages=[{
"role": "user",
"content": (
"다음 기사를 카테고리로 분류하세요. "
"카테고리: [기술, 경제, 스포츠, 문화, 정치, 사회]\n"
f"제목: {article['title']}\n"
f"요약: {article['summary']}"
)
}]
)
for article in articles
]
# ... 배치 실행 및 결과 매핑
패턴 2: SEO 메타 생성 배치
기존 기사 500편의 메타 디스크립션을 일괄 생성하거나 개선할 때 사용한다. 야간에 배치를 제출하면 다음날 아침 결과를 적용할 수 있다.
# 기사 본문 → SEO 메타 디스크립션 자동 생성
meta_prompt = """다음 기사 본문을 읽고 SEO 메타 디스크립션을 작성하세요.
조건: 155자 이내, 핵심 키워드 포함, 클릭 유도 문구 포함.
본문만 답하고 다른 설명은 하지 마세요."""
패턴 3: 다국어 번역 파이프라인
한국어 제품 설명 1,000건을 영어·일본어·중국어로 동시에 번역할 때, 언어별 배치를 병렬로 제출하면 처리 시간을 크게 줄일 수 있다.
# 언어별 배치를 동시에 제출 (병렬 처리)
target_languages = ["English", "Japanese", "Chinese"]
batch_ids = {}
for lang in target_languages:
batch = client.beta.messages.batches.create(
requests=build_translation_requests(texts, lang)
)
batch_ids[lang] = batch.id
print(f"{lang} 배치 제출: {batch.id}")
# 모든 배치 완료 대기
for lang, batch_id in batch_ids.items():
wait_for_batch(client, batch_id)
Batch API와 프롬프트 캐싱을 함께 적용하면 비용을 더 줄일 수 있다. 캐싱 전략에 대한 자세한 내용은 Claude 프롬프트 캐싱 완전 가이드를 참고하라.
Batch API 운영 팁
배치 크기 최적화: 10,000건 한도를 채울 필요는 없다. 1,000~5,000건 단위로 나누면 부분 실패 시 재처리 범위가 좁아진다.
폴링 간격: 30~60초가 적당하다. 소규모 배치(수백 건)는 수 분 내 완료되지만, 10,000건 대용량은 수 시간이 걸릴 수 있다.
실패 재처리: result.result.type == "errored" 인 요청만 추출해 별도 배치로 재제출하면 된다. 전체를 다시 실행할 필요가 없다.
비용 최적화 조합: Batch API(50% 절감) + 프롬프트 캐싱(최대 90% 절감)을 동시에 적용하면 동일 작업량 대비 총 비용을 90% 이상 줄이는 것도 가능하다.
Claude API 비용 최적화 완전판 — Batch API, 프롬프트 캐싱, 모델 라우팅을 모두 다루는 P5 Cost Optimization Masterclass를 확인하세요. 계산기 포함, 실전 파이프라인 코드 제공.
P5 Cost Optimization Masterclass 보기 →
Frequently Asked Questions
Batch API는 어떤 모델을 지원하나요?
Claude 3.5 Haiku, Claude Sonnet 4.5, Claude Opus 4.5 등 현재 Anthropic API에서 지원하는 주요 모델을 모두 Batch API로 사용할 수 있다. 배치 내 요청별로 서로 다른 모델을 지정할 수도 있다.
24시간 내 결과가 안 나오면 어떻게 되나요?
Anthropic은 24시간 내 결과 제공을 보장한다. 만약 24시간이 지나도 완료되지 않은 배치는 자동으로 취소되며, 과금되지 않은 요청은 환불된다. 실제로는 대부분의 배치가 수 분~수 시간 내에 완료된다.
배치 중간에 취소할 수 있나요?
client.beta.messages.batches.cancel(batch_id)로 진행 중인 배치를 취소할 수 있다. 이미 처리된 요청에 대해서는 비용이 청구되고, 처리되지 않은 요청은 과금되지 않는다.
실시간 API와 Batch API를 같은 프로젝트에서 혼용할 수 있나요?
가능하다. 사용자 대면 기능(챗봇, 실시간 응답)은 실시간 API를, 야간 데이터 처리나 백그라운드 분류 파이프라인은 Batch API로 분리하는 것이 이상적인 구조다. 동일한 API 키와 클라이언트 인스턴스를 재사용할 수 있다.