비용 사다리 — 마이크로컴팩트(무료)부터 세션 메모리, 전체 LLM 압축, 반응형 압축까지.
Claude Code의 컨텍스트 압축 시스템은 제한된 컨텍스트 윈도우를 효율적으로 활용하기 위해 4단계 전략을 사용합니다. 무료 로컬 변환부터 LLM 기반 요약까지, 비용과 품질의 균형을 맞추는 계층적 접근 방식입니다.
compaction/ 디렉토리 — compactor.ts, microCompact.ts, sessionMemoryCompact.ts, fullCompact.ts, reactiveCompact.ts, postCompactCleanup.ts
컨텍스트 윈도우의 유효 크기는 원시 윈도우보다 작습니다. 시스템 프롬프트(약 20K 토큰)와 압축 요약 출력용 예약 공간(약 20K 토큰)을 제외한 나머지가 실제 대화에 사용됩니다.
압축 전략은 비용이 낮은 순서대로 적용됩니다:
컨텍스트 사용량에 따라 세 가지 임계값이 압축을 트리거합니다:
마이크로컴팩트는 API 호출 없이 로컬에서 메시지를 변환하여 토큰을 절약합니다. 세 가지 경로가 있습니다:
오래된 메시지의 도구 결과를 축약합니다. 예를 들어 긴 파일 읽기 결과가 "파일 내용이 읽혔습니다 (4,230 토큰)" 같은 짧은 요약으로 대체됩니다.
일반 마이크로컴팩트와 달리, 서버 측 cache_edits를 큐잉하여 프롬프트 캐시를 보존합니다. 로컬에서 메시지를 직접 수정하면 캐시된 프롬프트 접두사가 무효화되므로, 캐시 마이크로컴팩트는 서버에 변경을 지시하여 캐시 히트율을 유지합니다.
이전에 읽은 파일이 변경되지 않았을 때, 도구 결과를 "파일이 이전 읽기 이후 변경되지 않았습니다"로 대체합니다.
// microCompact.ts — 캐시 보존 마이크로컴팩트
if (shouldUseCacheMicroCompact) {
// 서버 측 cache_edits 큐잉 — 프롬프트 캐시 보존
queueCacheEdit({
type: 'replace_content',
messageId: entry.uuid,
newContent: summary,
})
} else {
// 로컬 메시지 직접 변경 — 캐시 무효화 감수
entry.content = summary
}
Anthropic API의 프롬프트 캐싱은 동일한 메시지 접두사에 대해 서버 측 캐시를 유지합니다. 로컬에서 이전 메시지를 수정하면 접두사가 변경되어 전체 캐시가 무효화됩니다 (약 50~70K 토큰 재처리 비용). 캐시 마이크로컴팩트는 cache_edits를 사용하여 서버에서 직접 수정하므로, 캐시 히트를 유지하면서도 토큰을 절약합니다.
세션 메모리 압축은 추가 API 호출 없이 기존 세션 메모리에서 요약 정보를 활용합니다. 세션 동안 축적된 메모리 파일의 내용을 압축된 컨텍스트의 일부로 포함하여, 이전 대화의 핵심 결정 사항과 컨텍스트를 보존합니다.
마이크로컴팩트와 세션 메모리로 충분하지 않을 때, LLM에게 대화 전체를 요약하도록 요청합니다. 9개 섹션으로 구성된 요약 프롬프트를 사용합니다:
요약 프롬프트에는 <analysis> 스크래치패드가 포함됩니다. 모델이 먼저 대화를 분석한 후 구조화된 요약을 생성하도록 유도하여 요약 품질을 높입니다.
도구 사용 히스토리(섹션 5)는 수행된 작업을 캡처하지만, 사용자의 의도 전환은 놓칩니다. 예를 들어 "이제 테스트 대신 리팩토링에 집중하자"라는 사용자 메시지는 도구 기록에 반영되지 않습니다. 모든 사용자 메시지를 별도 섹션으로 포함하면 의도 변경, 우선순위 조정, 명시적 지시를 보존하여 압축 후에도 모델이 올바른 방향으로 작업을 계속할 수 있습니다.
반응형 압축은 API에서 413 (Payload Too Large) 에러가 반환될 때 트리거됩니다. 이는 마이크로컴팩트와 자동 압축으로도 충분히 줄이지 못한 극단적 상황에서의 비상 조치입니다.
압축 대상 메시지를 선택할 때, API 호출 라운드 단위로 그룹화합니다. 단일 메시지를 임의로 자르는 대신, 완전한 요청-응답 쌍을 유지하여 압축 후에도 대화의 논리적 일관성을 보장합니다.
adjustIndexToPreserveAPIInvariants압축 경계를 결정할 때, API 불변식 2가지를 보호합니다:
tool_use / tool_result 쌍: 도구 호출과 결과를 분리하지 않음runPostCompactCleanup)압축 완료 후 runPostCompactCleanup()이 캐시와 상태를 정리합니다:
getUserContext() 캐시 리셋 (메인 스레드에서만)runPostCompactCleanup은 서브에이전트 압축에서 getUserContext 캐시만 클리어하지 않습니다. 서브에이전트는 메인 스레드와 같은 프로세스에서 실행되어 모듈 상태를 공유하므로, 서브에이전트에서 이 캐시를 리셋하면 메인 스레드의 캐시가 손상됩니다.
/context 커맨드사용자가 수동으로 /context 커맨드를 입력하면 즉시 전체 LLM 압축이 트리거됩니다. 자동 임계값에 도달하기 전에 사용자가 능동적으로 컨텍스트를 관리할 수 있는 인터페이스입니다.
cache_edits를 사용하여 프롬프트 캐시를 보존합니다<analysis> 스크래치패드 패턴을 사용합니다adjustIndexToPreserveAPIInvariants가 tool_use/tool_result 쌍과 thinking 블록을 보호합니다getUserContext 캐시를 리셋하지 않는 이유는 같은 프로세스 공유 모듈 상태 때문입니다/context 커맨드로 수동 압축을 트리거할 수 있습니다Q1. 유효 컨텍스트 윈도우가 원시 윈도우보다 작은 주된 이유는?
Q2. 캐시 마이크로컴팩트와 일반 마이크로컴팩트의 주요 차이는?
cache_edits를 큐잉합니다. 로컬 수정은 프롬프트 접두사를 변경하여 서버 측 캐시를 무효화하지만, cache_edits는 캐시를 유지하면서 수정합니다.Q3. 9섹션 요약에 섹션 6 "모든 사용자 메시지"가 포함되는 이유는?
Q4. adjustIndexToPreserveAPIInvariants가 보호하는 2가지 불변식은?
tool_use와 tool_result 쌍이 분리되지 않도록 하고, thinking 블록의 중간에서 자르지 않도록 인덱스를 조정합니다. 이 두 불변식이 위반되면 API 호출이 실패합니다.Q5. runPostCompactCleanup이 서브에이전트 압축에서 getUserContext만 클리어하지 않는 이유는?
getUserContext 캐시를 리셋하면 메인 스레드가 사용 중인 캐시가 손상됩니다.