대부분의 팀이 AI API 호출에 과도한 비용을 지불하고 있습니다. 이는 모델을 잘못 선택해서가 아니라, 코드 변경을 최소화하면서 적용할 수 있는 세 가지 최적화 방법인 prompt caching, smart model routing, batch processing을 간과하고 있기 때문입니다.
실제 수치를 바탕으로 각 기술을 자세히 살펴보겠습니다.
현재 사용 중인 프로바이더 조합이 문제인지 고민 중이라면 가격 비교 글을 먼저 읽어보세요. 비용보다는 retry storm이나 프로바이더의 throttling이 더 큰 고민이라면 이 글과 함께 rate limiting 가이드를 참고하시기 바랍니다.
1. Prompt Caching: 가장 큰 효과를 볼 수 있는 방법
애플리케이션이 모든 요청마다 동일한 system prompt를 보낸다면, 프로바이더가 이미 처리한 token에 대해 중복으로 비용을 지불하고 있는 것입니다.
작동 원리
OpenAI는 1,024 token 이상의 입력에 대해 자동으로 prompt를 캐싱합니다. 캐싱된 token은 표준 input 가격의 50% 수준입니다. 코드를 변경할 필요가 없습니다.
Anthropic은 cache_control 중단점을 통해 명시적인 캐싱을 사용합니다. 쓰기 비용은 표준 input보다 25% 높지만, 읽기 비용은 90% 저렴합니다. 캐시 TTL은 5분이며, hit가 발생할 때마다 연장됩니다.
최신 OpenAI 가격 정책에서는 실제 할인 폭이 예상보다 클 수 있습니다. GPT-4.1의 캐싱된 input 가격은 표준 input의 4분의 1 수준으로 책정되어 있어, 일관된 접두사(prefix)를 사용하면 기존에 생각했던 것보다 훨씬 더 큰 비용 절감이 가능합니다.
비용 계산
일반적인 고객 지원 봇의 사례를 들어보겠습니다:
- System prompt: 2,000 tokens
- 사용자 메시지: 평균 200 tokens
- Claude Sonnet 4.6을 사용하여 일일 5,000건의 요청 처리
캐싱이 없는 경우:
일일 input 비용 = 5,000 × 2,200 tokens × $3.00/1M = $33.00
Anthropic prompt caching 적용 시 (cache hit rate 95% 가정):
캐시 쓰기: 250 × 2,200 × $3.75/1M = $2.06
캐시 읽기: 4,750 × 2,200 × $0.30/1M = $3.14
사용자 token: 5,000 × 200 × $3.00/1M = $3.00
일일 총합 = $8.20 (input 비용 75% 절감)
구현 방법
from anthropic import Anthropic
client = Anthropic(
api_key="sk-lemon-xxx",
base_url="https://api.lemondata.cc"
)
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are a customer support agent for Acme Corp...",
"cache_control": {"type": "ephemeral"} # 캐싱 활성화
}
],
messages=[{"role": "user", "content": user_message}]
)
# 응답 헤더에서 캐시 성능 확인
# cache_creation_input_tokens vs cache_read_input_tokens
OpenAI 모델의 경우 캐싱은 자동입니다. prompt가 1,024 token을 초과하는지 확인하고, 요청 간에 정적인 prefix를 일관되게 유지하기만 하면 됩니다.
흔히 범하는 실수:
- 모든 prompt 상단에 타임스탬프나 요청 ID를 넣는 경우
- 호출할 때마다 system instruction의 순서를 바꾸는 경우
- 고정된 prefix 앞에 가변적인 사용자 컨텍스트를 삽입하는 경우
prefix가 매번 바뀌면 캐시가 작동하지 않습니다. prompt의 구조를 단순한 prompt engineering의 디테일이 아닌, 비용을 결정하는 근본적인 요소로 다루어야 합니다.
2. Smart Model Routing: 각 작업에 적합한 모델 사용하기
모든 요청에 가장 비싼 모델을 사용할 필요는 없습니다. GPT-4.1이 input token 100만 개당 $2.00에 처리하는 분류(classification) 작업은 $0.40인 GPT-4.1-mini에서도 충분히 잘 수행될 수 있으며, 이는 5배의 비용 절감을 의미합니다.
라우팅 전략
| 작업 유형 | 추천 모델 | Input 비용/1M |
|---|---|---|
| 복잡한 추론 | Claude Opus 4.6 / GPT-4.1 | $5.00 / $2.00 |
| 일반적인 대화 | Claude Sonnet 4.6 / GPT-4.1 | $3.00 / $2.00 |
| 분류, 데이터 추출 | GPT-4.1-mini / Claude Haiku 4.5 | $0.40 / $1.00 |
| Embeddings | text-embedding-3-small | $0.02 |
| 단순 포맷팅 | DeepSeek V3 | $0.28 |
구현 방법
from openai import OpenAI
client = OpenAI(
api_key="sk-lemon-xxx",
base_url="https://api.lemondata.cc/v1"
)
def route_request(task_type: str, messages: list) -> str:
"""해당 작업을 잘 처리하면서 가장 저렴한 모델을 선택합니다."""
model_map = {
"classification": "gpt-4.1-mini",
"extraction": "gpt-4.1-mini",
"summarization": "gpt-4.1-mini",
"complex_reasoning": "gpt-4.1",
"creative_writing": "claude-sonnet-4-6",
"code_generation": "claude-sonnet-4-6",
}
model = model_map.get(task_type, "gpt-4.1-mini")
response = client.chat.completions.create(
model=model,
messages=messages
)
return response.choices[0].message.content
실제 절감 효과
요청의 60%(linting, 포맷팅, 단순 완성)를 GPT-4.1-mini로 보내고, 40%(아키텍처, 디버깅)를 Claude Sonnet 4.6으로 보내는 코딩 어시스턴트의 경우:
변경 전 (모두 Claude Sonnet 4.6 사용):
일일 1,000건 × 3K input × $3.00/1M = $9.00/일
변경 후 (60/40 분할):
600건 × 3K × $0.40/1M = $0.72/일 (mini)
400건 × 3K × $3.00/1M = $3.60/일 (sonnet)
총합 = $4.32/일 (52% 절감)
3. Batch Processing: 긴급하지 않은 작업을 위한 저렴한 가격
OpenAI는 input 및 output token에 대해 50% 할인을 제공하는 Batch API를 운영하고 있습니다. 대신 결과는 실시간이 아닌 24시간 이내에 제공됩니다.
Anthropic 역시 지원되는 모델에 대해 50% batch 할인을 제공합니다. 작업 부하가 야간에 발생하거나, 비동기적이거나, 검토 중심의 작업이라면 실시간 가격을 지불할 이유가 거의 없습니다.
batch 처리에 적합한 작업:
- 야간 콘텐츠 생성
- 대량 문서 분류
- 데이터셋 레이블링
- 정기 보고서 생성
# batch 파일 생성 (JSONL 형식)
import json
requests = []
for i, doc in enumerate(documents):
requests.append({
"custom_id": f"doc-{i}",
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": "gpt-4.1-mini",
"messages": [
{"role": "system", "content": "Classify this document..."},
{"role": "user", "content": doc}
]
}
})
# JSONL 파일 쓰기
with open("batch_input.jsonl", "w") as f:
for req in requests:
f.write(json.dumps(req) + "\n")
# batch 제출
batch_file = client.files.create(file=open("batch_input.jsonl", "rb"), purpose="batch")
batch = client.batches.create(input_file_id=batch_file.id, endpoint="/v1/chat/completions", completion_window="24h")
실제 제품 내에서 batch 처리에 적합한 사례:
- 야간 콘텐츠 업데이트 작업
- 고객 지원 티켓 요약
- embeddings 백필(backfills)
- 대규모 코드베이스 또는 문서 검토
- 우선순위가 낮은 사용자 알림
부적합한 사례:
- 채팅 응답
- 대화형 코딩 지원
- 다음 사용자 행동이 즉각적인 답변에 의존하는 워크플로우
4. 보너스: Token 수 줄이기
API 수준에서 최적화하기 전에, 필요 이상의 token을 보내고 있지는 않은지 확인해 보세요.
흔한 낭비 사례:
- 모델이 이미 따르고 있는 지침을 반복하는 장황한 system prompt
- 마지막 3~5개 대화만 중요한데도 전체 대화 기록을 포함하는 경우
- 일반 텍스트로도 충분한데 원본 HTML/markdown을 보내는 경우
- output 길이를 제한하기 위해
max_tokens를 사용하지 않는 경우
prompt 길이를 30% 줄이면 input 비용이 즉시 30% 절감됩니다.
낭비를 찾는 가장 쉬운 방법은 경로(route)나 기능별로 prompt 길이를 로깅하는 것입니다. 대부분의 팀은 모델 가격 책정의 문제가 아니라, "비대해진 동일한 prompt가 하루에 10만 번씩 전송되는" 문제를 가지고 있습니다.
5. 무작정 최적화하기 전에 비용 가시성 확보하기
직관에 의존한 최적화는 실패하기 마련입니다.
라우팅 규칙을 변경하기 전에 다음 항목을 로깅하세요:
- 경로 또는 기능 이름
- 모델
- input tokens
- output tokens
- 캐시 hit 또는 miss
- retry 횟수
- 사용자가 체감하는 latency
이를 통해 다음과 같은 핵심 질문에 답할 수 있어야 합니다:
- 어떤 경로가 정말 유용해서 비용이 많이 발생하는가?
- 어떤 경로가 prompt 낭비 때문에 비용이 많이 발생하는가?
- 어떤 경로를 batch로 전환해야 하는가?
- 어떤 경로를 더 저렴한 모델 티어로 옮겨야 하는가?
이 네 가지 질문에 답할 수 없다면, 여러분의 "비용 최적화"는 그저 비용을 이리저리 옮기는 것에 불과할 것입니다.
6. 실제 최적화 순서
가장 효과적인 순서는 보통 다음과 같습니다:
- 명백한 token 낭비를 제거합니다.
- 캐싱을 활성화하거나 수정합니다.
- 저렴한 작업과 비싼 작업을 분리합니다.
- 긴급하지 않은 모든 작업을 batch로 처리합니다.
- 그다음에 프로바이더 조합을 재협상합니다.
이 순서가 중요한 이유는 프로바이더를 바꾸기 전에 이미 큰 절감이 가능하기 때문입니다. prompt 구조를 고치지 않고 벤더만 바꾸면 동일한 비효율성에 대해 계속 비용을 지불하게 됩니다.
7. 구체적인 도입 전후 사례
현재 모든 요청에 대해 다음과 같이 작동하는 고객 지원 워크플로우를 가정해 보겠습니다:
- 2,000 token의 system prompt 전송
- 모든 요청에 하나의 프리미엄 모델 호출
- 일시적 장애 시 동일한 형태의 요청 재시도
- 야간 요약 작업을 batch가 아닌 동기 방식으로 실행
첫 번째 버전은 코드 경로가 하나뿐이라 "단순"해 보일 수 있지만, 재정적으로는 네 가지 비싼 일을 동시에 하고 있는 셈입니다.
더 효율적인 도입 방식은 다음과 같습니다:
- 고정된 정책 텍스트를 prompt 앞부분으로 옮겨 캐시가 실제로 작동하게 합니다.
- 분류, 추출, 짧은 요약은 더 저렴한 모델 티어로 라우팅합니다.
- 프리미엄 모델은 에스컬레이션, 복잡한 추론 또는 최종 답변 합성용으로 남겨둡니다.
- 야간 요약 및 백필 작업은 batch로 전환합니다.
- 매주 로그를 검토하여 prompt 구조가 변해 캐시 효율이 떨어진 경로가 있는지 확인합니다.
이러한 방식은 전체 코드를 다시 짤 필요가 없습니다. 일주일 정도의 계측(instrumentation)과 prompt 및 라우팅을 프로덕션의 주요 요소로 관리하려는 의지만 있으면 됩니다.
8. 하지 말아야 할 것들
비용 최적화 노력을 낭비하는 가장 빠른 방법은 엉뚱한 것을 최적화하는 것입니다.
다음과 같은 함정을 피하세요:
- prompt 낭비를 측정하기도 전에 프로바이더부터 바꾸는 것
- 출력 품질을 검증하지 않고 저렴한 모델로 작업을 라우팅하는 것
- 매 요청마다 prefix가 바뀌는 prompt에 캐싱을 설정하는 것
- 실시간 응답이 필요한 사용자 대면 작업을 batch로 처리하는 것
- token 가격만 보고 retry, latency, fallback 오버헤드를 무시하는 것
비용 최적화는 비용을 절감한 후에도 제품이 여전히 잘 작동할 때 성공한 것입니다. UX가 나빠진다면 스프레드시트상의 승리는 가짜일 뿐입니다.
요약
| 기술 | 노력 수준 | 일반적인 절감 효과 |
|---|---|---|
| Prompt caching | 낮음 (cache_control 추가) | input의 40-75% |
| Model routing | 중간 (작업 분류) | 전체의 30-50% |
| Batch processing | 중간 (비동기 워크플로우) | batch 작업의 50% |
| Token reduction | 낮음 (prompt 다듬기) | input의 10-30% |
이러한 기술들은 중첩되어 효과를 냅니다. 네 가지를 모두 구현한 팀은 출력 품질의 저하 없이 월간 API 비용을 $3,000에서 $1,000 미만으로 현실적으로 줄일 수 있습니다.
핵심 통찰: AI API 비용 최적화는 더 저렴한 프로바이더를 찾는 것이 아닙니다. 각 특정 작업에 대해 적절한 가격 티어의 적절한 모델을 적절한 캐싱 전략과 함께 사용하는 것입니다.
이미 여러 프로바이더를 사용 중이라면 운영 측면도 중요합니다. 마이그레이션 가이드와 OpenRouter 비교를 통해 개별 통합을 계속 수정하는 대신 라우팅을 중앙 집중화할 시점을 결정해 보세요.
오늘부터 최적화를 시작하세요: LemonData는 하나의 API key로 300개 이상의 모델에 대한 접근을 제공하며, OpenAI 및 Anthropic 모델 제품군에 대한 prompt caching 지원과 사용량을 한곳에서 비교할 수 있는 기능을 제공합니다.
