컨텍스트 압축

비용 사다리 — 마이크로컴팩트(무료)부터 세션 메모리, 전체 LLM 압축, 반응형 압축까지.

01

개요

Claude Code의 컨텍스트 압축 시스템은 제한된 컨텍스트 윈도우를 효율적으로 활용하기 위해 4단계 전략을 사용합니다. 무료 로컬 변환부터 LLM 기반 요약까지, 비용과 품질의 균형을 맞추는 계층적 접근 방식입니다.

다루는 소스 파일: compaction/ 디렉토리 — compactor.ts, microCompact.ts, sessionMemoryCompact.ts, fullCompact.ts, reactiveCompact.ts, postCompactCleanup.ts

컨텍스트 윈도우의 유효 크기는 원시 윈도우보다 작습니다. 시스템 프롬프트(약 20K 토큰)와 압축 요약 출력용 예약 공간(약 20K 토큰)을 제외한 나머지가 실제 대화에 사용됩니다.

02

4전략 비용 사다리

압축 전략은 비용이 낮은 순서대로 적용됩니다:

  1. Microcompact (무료): API 호출 없이 로컬에서 메시지를 변환
  2. Session Memory (무료): 세션 메모리에서 요약을 생성 (API 호출 없음)
  3. Full LLM Compaction (유료): LLM에게 대화를 요약하도록 요청
  4. Reactive Compaction (유료): API 413 에러 시 긴급 압축

임계값

컨텍스트 사용량에 따라 세 가지 임계값이 압축을 트리거합니다:

03

마이크로컴팩트

마이크로컴팩트는 API 호출 없이 로컬에서 메시지를 변환하여 토큰을 절약합니다. 세 가지 경로가 있습니다:

1. 시간 기반 마이크로컴팩트

오래된 메시지의 도구 결과를 축약합니다. 예를 들어 긴 파일 읽기 결과가 "파일 내용이 읽혔습니다 (4,230 토큰)" 같은 짧은 요약으로 대체됩니다.

2. 캐시 마이크로컴팩트

일반 마이크로컴팩트와 달리, 서버 측 cache_edits를 큐잉하여 프롬프트 캐시를 보존합니다. 로컬에서 메시지를 직접 수정하면 캐시된 프롬프트 접두사가 무효화되므로, 캐시 마이크로컴팩트는 서버에 변경을 지시하여 캐시 히트율을 유지합니다.

3. 미변경 마이크로컴팩트

이전에 읽은 파일이 변경되지 않았을 때, 도구 결과를 "파일이 이전 읽기 이후 변경되지 않았습니다"로 대체합니다.

// 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를 사용하여 서버에서 직접 수정하므로, 캐시 히트를 유지하면서도 토큰을 절약합니다.

04

세션 메모리 압축

세션 메모리 압축은 추가 API 호출 없이 기존 세션 메모리에서 요약 정보를 활용합니다. 세션 동안 축적된 메모리 파일의 내용을 압축된 컨텍스트의 일부로 포함하여, 이전 대화의 핵심 결정 사항과 컨텍스트를 보존합니다.

05

전체 LLM 압축

마이크로컴팩트와 세션 메모리로 충분하지 않을 때, LLM에게 대화 전체를 요약하도록 요청합니다. 9개 섹션으로 구성된 요약 프롬프트를 사용합니다:

  1. 현재 작업 상태 — 진행 중인 작업과 다음 단계
  2. 완료된 작업 — 성공적으로 끝난 작업 목록
  3. 핵심 결정 사항 — 사용자와 합의한 설계 결정
  4. 중요 파일 경로 — 작업에 관련된 파일 목록
  5. 도구 사용 히스토리 — 실행된 도구와 결과 요약
  6. 모든 사용자 메시지 — 사용자의 전체 지시 사항
  7. 에러 및 해결 — 발생한 오류와 해결 방법
  8. 환경 컨텍스트 — 프로젝트 구조, 기술 스택 등
  9. 제약 사항 — 사용자가 설정한 제한 조건

analysis 스크래치패드 패턴

요약 프롬프트에는 <analysis> 스크래치패드가 포함됩니다. 모델이 먼저 대화를 분석한 후 구조화된 요약을 생성하도록 유도하여 요약 품질을 높입니다.

딥 다이브 — 섹션 6 "모든 사용자 메시지" 포함 이유

도구 사용 히스토리(섹션 5)는 수행된 작업을 캡처하지만, 사용자의 의도 전환은 놓칩니다. 예를 들어 "이제 테스트 대신 리팩토링에 집중하자"라는 사용자 메시지는 도구 기록에 반영되지 않습니다. 모든 사용자 메시지를 별도 섹션으로 포함하면 의도 변경, 우선순위 조정, 명시적 지시를 보존하여 압축 후에도 모델이 올바른 방향으로 작업을 계속할 수 있습니다.

06

반응형 압축

반응형 압축은 API에서 413 (Payload Too Large) 에러가 반환될 때 트리거됩니다. 이는 마이크로컴팩트와 자동 압축으로도 충분히 줄이지 못한 극단적 상황에서의 비상 조치입니다.

API 라운드별 메시지 그루핑

압축 대상 메시지를 선택할 때, API 호출 라운드 단위로 그룹화합니다. 단일 메시지를 임의로 자르는 대신, 완전한 요청-응답 쌍을 유지하여 압축 후에도 대화의 논리적 일관성을 보장합니다.

adjustIndexToPreserveAPIInvariants

압축 경계를 결정할 때, API 불변식 2가지를 보호합니다:

07

후처리 정리 (runPostCompactCleanup)

압축 완료 후 runPostCompactCleanup()이 캐시와 상태를 정리합니다:

주의사항

runPostCompactCleanup은 서브에이전트 압축에서 getUserContext 캐시만 클리어하지 않습니다. 서브에이전트는 메인 스레드와 같은 프로세스에서 실행되어 모듈 상태를 공유하므로, 서브에이전트에서 이 캐시를 리셋하면 메인 스레드의 캐시가 손상됩니다.

/context 커맨드

사용자가 수동으로 /context 커맨드를 입력하면 즉시 전체 LLM 압축이 트리거됩니다. 자동 임계값에 도달하기 전에 사용자가 능동적으로 컨텍스트를 관리할 수 있는 인터페이스입니다.

08

핵심 요약

핵심 포인트

  • 4단계 비용 사다리: Microcompact(무료) → Session Memory(무료) → Full LLM(유료) → Reactive(유료)
  • 유효 컨텍스트 윈도우는 원시 윈도우에서 시스템 프롬프트와 압축 출력 예약분(약 20K)을 뺀 크기입니다
  • 캐시 마이크로컴팩트는 서버 측 cache_edits를 사용하여 프롬프트 캐시를 보존합니다
  • 전체 LLM 압축은 9섹션 요약 프롬프트와 <analysis> 스크래치패드 패턴을 사용합니다
  • 섹션 6 "모든 사용자 메시지"는 도구 히스토리가 놓치는 사용자 의도 전환을 보존합니다
  • adjustIndexToPreserveAPIInvariants가 tool_use/tool_result 쌍과 thinking 블록을 보호합니다
  • 서브에이전트 압축에서 getUserContext 캐시를 리셋하지 않는 이유는 같은 프로세스 공유 모듈 상태 때문입니다
  • /context 커맨드로 수동 압축을 트리거할 수 있습니다
09

지식 확인

퀴즈 — 5문제

Q1. 유효 컨텍스트 윈도우가 원시 윈도우보다 작은 주된 이유는?

  • A) 시스템 프롬프트가 약 20K 토큰을 차지하기 때문
  • B) 압축 요약 출력용으로 약 20K 토큰이 예약되어 있기 때문
  • C) 이미지 오버헤드 때문
  • D) AUTOCOMPACT 상수로 인해
유효 윈도우는 원시 윈도우에서 시스템 프롬프트와 압축 요약 출력을 위한 예약 공간(약 20K 토큰)을 뺀 크기입니다. 이 예약 공간은 압축 시 요약을 생성할 여유를 확보합니다.

Q2. 캐시 마이크로컴팩트와 일반 마이크로컴팩트의 주요 차이는?

  • A) 추가 API 호출이 필요함
  • B) 디스크에 저장함
  • C) 로컬 메시지 변경 대신 서버 측 cache_edits를 큐잉하여 프롬프트 캐시를 보존
  • D) 24시간 이상 된 메시지만 대상
캐시 마이크로컴팩트는 로컬에서 메시지를 직접 수정하지 않고, 서버에 cache_edits를 큐잉합니다. 로컬 수정은 프롬프트 접두사를 변경하여 서버 측 캐시를 무효화하지만, cache_edits는 캐시를 유지하면서 수정합니다.

Q3. 9섹션 요약에 섹션 6 "모든 사용자 메시지"가 포함되는 이유는?

  • A) 규정 준수를 위해
  • B) 도구 사용 히스토리는 수행된 내용을 캡처하지만 사용자의 의도 전환은 놓치기 때문
  • C) 크기가 작아서
  • D) 요약기 모델이 약해서
도구 사용 히스토리(섹션 5)는 실행된 작업을 기록하지만, "이제 테스트 대신 리팩토링에 집중하자" 같은 사용자의 방향 전환은 포착하지 못합니다. 사용자 메시지를 별도로 보존하면 의도 변경과 우선순위 조정이 압축 후에도 유지됩니다.

Q4. adjustIndexToPreserveAPIInvariants가 보호하는 2가지 불변식은?

  • A) tool_use/tool_result 쌍과 thinking 블록
  • B) 최소/최대 토큰 수
  • C) 경계 마커와 메모리 파일
  • D) 첨부 파일과 MCP 스키마
압축 경계를 결정할 때, tool_usetool_result 쌍이 분리되지 않도록 하고, thinking 블록의 중간에서 자르지 않도록 인덱스를 조정합니다. 이 두 불변식이 위반되면 API 호출이 실패합니다.

Q5. runPostCompactCleanup이 서브에이전트 압축에서 getUserContext만 클리어하지 않는 이유는?

  • A) CLAUDE.md를 사용하지 않아서
  • B) 별도 프로세스에서 실행되어서
  • C) 같은 프로세스 공유 모듈 상태 — 서브에이전트에서 리셋 시 메인 스레드 캐시 손상
  • D) 짧은 윈도우 때문
서브에이전트는 별도 프로세스가 아니라 메인 스레드와 같은 프로세스에서 실행됩니다. 모듈 수준의 캐시 상태를 공유하므로, 서브에이전트에서 getUserContext 캐시를 리셋하면 메인 스레드가 사용 중인 캐시가 손상됩니다.
0 / 5