콘텐츠로 이동

비용 최적화와 모델 라우팅

소규모 프로젝트에서 에이전트 비용은 무시할 수 있는 수준입니다. 하지만 팀이 에이전트를 적극 활용하기 시작하면 비용이 빠르게 증가합니다.

개인 사용: $10~50/월 → 무시 가능
소규모 팀: $200~500/월 → 최적화 고려
프로덕션 팀: $2,000+/월 → 전략적 최적화 필수

비용 최적화는 단순히 돈을 아끼는 것이 아닙니다. 올바른 도구를 올바른 작업에 사용하는 엔지니어링 판단의 문제입니다.

모델특성적합한 작업상대 비용
Haiku빠름, 저렴, 간단한 추론분류, 요약, 포맷 변환1x
Sonnet균형, 표준 코딩일반 코드 작성, 디버깅5x
Opus느림, 고비용, 깊은 추론아키텍처 설계, 복잡한 분석15x
harness/model-router.ts
type TaskComplexity = 'simple' | 'standard' | 'complex'
interface RoutingRule {
keywords: string[]
maxTokens: number
complexity: TaskComplexity
}
const ROUTING_RULES: RoutingRule[] = [
{
keywords: ['classify', 'summarize', 'format', 'extract', 'translate'],
maxTokens: 1000,
complexity: 'simple'
},
{
keywords: ['implement', 'fix', 'refactor', 'test', 'debug'],
maxTokens: 4000,
complexity: 'standard'
},
{
keywords: ['architect', 'design', 'analyze', 'review', 'optimize'],
maxTokens: 8000,
complexity: 'complex'
}
]
function routeTask(task: string, contextSize: number): string {
const lowerTask = task.toLowerCase()
for (const rule of ROUTING_RULES) {
const matches = rule.keywords.some(kw => lowerTask.includes(kw))
if (matches && contextSize <= rule.maxTokens) {
return modelForComplexity(rule.complexity)
}
}
return 'claude-sonnet-4-5' // 기본값
}
function modelForComplexity(complexity: TaskComplexity): string {
const models: Record<TaskComplexity, string> = {
simple: 'claude-haiku-4-5',
standard: 'claude-sonnet-4-5',
complex: 'claude-opus-4-5'
}
return models[complexity]
}

KV-cache(Key-Value Cache)는 반복되는 컨텍스트를 캐싱하여 API 비용을 대폭 줄이는 기술입니다.

일반 요청:
시스템 프롬프트 (2,000 토큰) → 매번 전체 처리
비용: 2,000 × $0.003/1K = $0.006/요청
캐시 적용:
시스템 프롬프트 첫 요청 → 캐시 저장 (일반 비용)
이후 요청 → 캐시 히트 (10% 비용)
비용: 2,000 × $0.0003/1K = $0.0006/요청
→ 10배 비용 절감
harness/cached-client.ts
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic()
async function runWithCache(
systemPrompt: string,
userMessage: string
): Promise<string> {
const response = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 4096,
system: [
{
type: 'text',
text: systemPrompt,
// 시스템 프롬프트를 캐시 대상으로 지정
cache_control: { type: 'ephemeral' }
}
],
messages: [
{ role: 'user', content: userMessage }
]
})
// 캐시 사용 통계 로깅
const usage = response.usage
console.info('Cache stats:', {
inputTokens: usage.input_tokens,
cacheCreationTokens: usage.cache_creation_input_tokens,
cacheReadTokens: usage.cache_read_input_tokens
})
return response.content[0].type === 'text' ? response.content[0].text : ''
}
높은 캐시 히트율을 위한 설계:
1. 정적 컨텐츠를 앞에 배치
[시스템 프롬프트 - 캐시] + [사용자 입력 - 비캐시]
2. AGENTS.md를 시스템 프롬프트에 포함
매 요청마다 동일한 컨텐츠 → 높은 히트율
3. 대화 히스토리 전략
오래된 메시지 압축/요약 후 캐시 경계 이전으로 이동
harness/token-budget.ts
interface TokenBudget {
maxInputTokens: number
maxOutputTokens: number
warningThreshold: number // 경고 발생 비율
}
const TOKEN_BUDGETS: Record<string, TokenBudget> = {
codeGeneration: {
maxInputTokens: 8_000,
maxOutputTokens: 4_000,
warningThreshold: 0.8
},
codeReview: {
maxInputTokens: 16_000,
maxOutputTokens: 2_000,
warningThreshold: 0.8
},
architectureAnalysis: {
maxInputTokens: 32_000,
maxOutputTokens: 8_000,
warningThreshold: 0.9
}
}
function validateTokenUsage(
taskType: string,
inputTokens: number
): { allowed: boolean; warning: string | null } {
const budget = TOKEN_BUDGETS[taskType]
if (!budget) return { allowed: true, warning: null }
if (inputTokens > budget.maxInputTokens) {
return {
allowed: false,
warning: `토큰 예산 초과: ${inputTokens} > ${budget.maxInputTokens}`
}
}
if (inputTokens > budget.maxInputTokens * budget.warningThreshold) {
return {
allowed: true,
warning: `토큰 예산 ${Math.round(inputTokens / budget.maxInputTokens * 100)}% 사용 중`
}
}
return { allowed: true, warning: null }
}
harness/cost-tracker.ts
interface CostRecord {
timestamp: Date
model: string
taskType: string
inputTokens: number
outputTokens: number
cacheReadTokens: number
estimatedCost: number
}
const COST_PER_1K: Record<string, { input: number; output: number; cacheRead: number }> = {
'claude-haiku-4-5': { input: 0.00025, output: 0.00125, cacheRead: 0.000025 },
'claude-sonnet-4-5': { input: 0.003, output: 0.015, cacheRead: 0.0003 },
'claude-opus-4-5': { input: 0.015, output: 0.075, cacheRead: 0.0015 }
}
function calculateCost(record: Omit<CostRecord, 'estimatedCost'>): number {
const rates = COST_PER_1K[record.model]
if (!rates) return 0
return (
(record.inputTokens / 1000) * rates.input +
(record.outputTokens / 1000) * rates.output +
(record.cacheReadTokens / 1000) * rates.cacheRead
)
}
.github/workflows/cost-alert.yml
name: Daily Cost Alert
on:
schedule:
- cron: '0 9 * * *' # 매일 오전 9시
jobs:
check-cost:
runs-on: ubuntu-latest
steps:
- name: Check daily spend
run: |
DAILY_COST=$(node scripts/get-daily-cost.js)
BUDGET=50 # $50/일 예산
if (( $(echo "$DAILY_COST > $BUDGET" | bc -l) )); then
echo "::warning::일일 비용 초과: $${DAILY_COST} (예산: $${BUDGET})"
# Slack 알림 전송
curl -X POST $SLACK_WEBHOOK \
-d "{\"text\": \"AI 에이전트 일일 비용 경고: \$${DAILY_COST}\"}"
fi
항목예상 절감 효과
단순 작업 → Haiku 라우팅60~80% (해당 작업)
KV-cache 시스템 프롬프트 캐싱40~60% (캐시 히트율 50% 기준)
컨텍스트 압축 (불필요한 토큰 제거)20~30%
배치 처리 (실시간 불필요한 요청 묶기)10~20%
토큰 예산 강제 적용예산 초과 방지

비용 최적화는 모델 라우팅, KV-cache, 토큰 예산 관리의 세 축으로 구성됩니다. 작업 복잡도에 맞는 모델을 자동으로 선택하고, 반복되는 시스템 프롬프트를 캐싱하며, 토큰 사용량을 모니터링하면 품질 저하 없이 비용을 50~70% 절감할 수 있습니다.