클로드 코드(Claude Code) 소스코드 분석 시리즈입니다. cost-tracker는 API 호출마다 토큰과 비용을 실시간 집계합니다. 입력/출력/캐시읽기/캐시쓰기 네 가지로 분류해서 추적하고, 모델별 단가표를 적용해 USD 비용을 산출합니다. 대화가 길어지면 compact 서비스가 자동으로 컨텍스트를 압축해서 비용 폭주를 막습니다.
시리즈: Part 16 — 숨겨진 비밀 기능들 | Part 17 | Part 18 — 51만 줄에서 배운 것
목차
- API 호출마다 토큰을 어떻게 추적하나?
- 모델별 가격 차이는 얼마나 되나?
- 대화가 길어지면 자동으로 압축되나?
- 압축마저 실패하면?
- 비용 최적화의 세 가지 축
API 호출마다 토큰을 어떻게 추적하나?
핵심은 addToTotalSessionCost 함수입니다. API 응답이 올 때마다 호출되면서 토큰과 비용이 누적됩니다.
// cost-tracker.ts
export function addToTotalSessionCost(
cost: number, usage: Usage, model: string
): number {
const modelUsage = addToTotalModelUsage(cost, usage, model)
addToTotalCostState(cost, modelUsage, model)
getCostCounter()?.add(cost, attrs)
getTokenCounter()?.add(usage.input_tokens,
{ ...attrs, type: 'input' })
getTokenCounter()?.add(usage.output_tokens,
{ ...attrs, type: 'output' })
getTokenCounter()?.add(usage.cache_read_input_tokens ?? 0,
{ ...attrs, type: 'cacheRead' })
getTokenCounter()?.add(usage.cache_creation_input_tokens ?? 0,
{ ...attrs, type: 'cacheCreation' })
// ...
}
토큰을 input, output, cacheRead, cacheCreation 네 가지 타입으로 분류합니다. 프롬프트 캐싱의 절약 효과를 실시간으로 확인할 수 있는 구조입니다.
세션이 끝나면 saveCurrentSessionCosts가 프로젝트 설정 파일에 비용을 저장하고, 다음에 같은 세션을 이어갈 때 restoreCostStateForSession으로 복원합니다. 껐다 켜도 비용 추적이 끊기지 않습니다.
모델별 가격 차이는 얼마나 되나?
modelCost.ts에 모델별 단가표가 하드코딩되어 있습니다. 백만 토큰(Mtok) 기준 USD 단가입니다.
// modelCost.ts — 모델별 단가 (입력/출력 per Mtok)
COST_HAIKU_35: { inputTokens: 0.8, outputTokens: 4 }
COST_TIER_3_15: { inputTokens: 3, outputTokens: 15 } // Sonnet
COST_TIER_15_75: { inputTokens: 15, outputTokens: 75 } // Opus 4/4.1
COST_TIER_5_25: { inputTokens: 5, outputTokens: 25 } // Opus 4.5/4.6
COST_TIER_30_150:{ inputTokens: 30, outputTokens: 150 } // Opus 4.6 Fast
Haiku 대비 Opus 4의 출력 단가가 약 19배입니다. 같은 작업이라도 모델 선택에 따라 비용이 크게 달라집니다. 실제 비용 산출은 tokensToUSDCost가 각 토큰 타입에 단가를 곱해서 합산하는 단순한 구조입니다.
Opus 4.6은 특이하게 Fast 모드 여부에 따라 단가가 달라집니다. usage.speed === 'fast'이면 $30/$150, 아니면 $5/$25입니다.
대화가 길어지면 자동으로 압축되나?
컨텍스트 윈도우에서 13,000토큰 여유분을 뺀 지점이 자동 압축 임계값입니다. 이 임계값을 넘으면 compact가 자동 실행됩니다.
// autoCompact.ts
export const AUTOCOMPACT_BUFFER_TOKENS = 13_000
export function getAutoCompactThreshold(model: string): number {
const effectiveContextWindow =
getEffectiveContextWindowSize(model)
return effectiveContextWindow - AUTOCOMPACT_BUFFER_TOKENS
}
압축이 실행되면 compactConversation이 기존 대화를 LLM에게 보내 요약을 생성합니다. 요약 프롬프트에는 "파일명, 코드 스니펫, 에러와 해결 방법, 사용자 피드백을 반드시 포함하라"는 상세한 지침이 들어갑니다.
요약 후에는 최근 읽었던 중요한 파일을 최대 5개, 50,000토큰 예산 내에서 다시 주입합니다(POST_COMPACT_TOKEN_BUDGET = 50_000). 무작정 압축하는 게 아니라 복원할 컨텍스트의 양까지 계산하는 겁니다.

압축마저 실패하면?
요약 요청 자체가 컨텍스트 윈도우를 넘기는 상황도 발생합니다. 이때 truncateHeadForPTLRetry가 가장 오래된 메시지 그룹부터 제거하면서 최대 3번 재시도합니다.
// compact.ts
const tokenGap = getPromptTooLongTokenGap(ptlResponse)
if (tokenGap !== undefined) {
// tokenGap만큼 오래된 그룹 제거
} else {
dropCount = Math.max(1, Math.floor(groups.length * 0.2))
}
토큰 초과량을 알면 정확히 그만큼만, 모르면 전체의 20%를 잘라냅니다. 3번 연속 실패하면 서킷 브레이커가 작동해서 더 이상 시도하지 않습니다. 소스 주석에 "last-resort escape hatch"라고 적혀 있을 만큼 최후의 안전장치입니다.
비용 최적화의 세 가지 축
Claude Code의 비용 관리는 세 가지 축으로 구성됩니다.
프롬프트 캐싱: 캐시 읽기 단가는 입력 단가의 1/10입니다. Sonnet 기준 입력 $3/Mtok인데 캐시 읽기는 $0.3/Mtok. 같은 시스템 프롬프트를 반복 전송해도 캐시 히트면 비용이 거의 없습니다. 관련 글: 프롬프트 캐싱 분석
모델 라우팅: 간단한 작업에 Haiku($0.8/Mtok), 복잡한 작업에 Opus($15/Mtok). 비용 테이블이 모델별로 분리되어 있어서 라우팅의 절감 효과를 정확히 추적할 수 있습니다.
컨텍스트 압축: 대화가 길어지면 요약해서 토큰 수를 줄입니다. 압축 실패 시 메시지 제거, 그마저 실패하면 서킷 브레이커까지 다단계 폴백이 작동합니다. 이 구조 덕분에 하루 종일 대화해도 비용이 선형 증가하지 않습니다.
LLM 기반 서비스를 만든다면, 토큰을 타입별로 분리 추적하고 모델별 단가를 명시적으로 관리하는 이 패턴을 참고할 만합니다.
'AI 코딩 에이전트' 카테고리의 다른 글
| Claude Code 해부학 이후: AI 코딩 에이전트 설계 원리 7가지 (5) | 2026.04.04 |
|---|---|
| Claude Code 51만 줄에서 배운 것: AI 제품을 만들고 싶은 개발자에게 (해부학 Part 18) (0) | 2026.04.02 |
| Claude Code에 숨겨진 비밀 기능들: 다마고치, 카피바라, 언더커버 모드 (해부학 Part 16) (0) | 2026.04.02 |
| Claude Code 빌드 시스템 분석: Bun 번들러와 유출의 원인 (해부학 Part 15) (0) | 2026.04.02 |
| Claude Code IDE 브릿지 분석: VS Code 안에서 동작하는 원리 (해부학 Part 14) (0) | 2026.04.02 |
