이 글은 Anthropic Claude Code 팀의 Thariq(@trq212)이 공유한 Lessons from Building Claude Code: Prompt Caching Is Everything 스레드를 기반으로, 프롬프트 캐싱의 원리와 실전 레슨을 정리한 글입니다. Claude Code의
/context출력 분석과 Compaction API, Tool Search 등 관련 주제를 포함합니다.
PART 1. 프롬프트 캐싱의 의미
1. 에이전트 시스템에서 캐싱이 중요한 이유
2. 프롬프트 캐싱의 핵심 원리: Prefix Matching
PART 2. Claude Code에서 배운 실전 레슨
3. 정적 콘텐츠를 앞에, 동적 콘텐츠를 뒤에
4. 시스템 프롬프트를 수정하지 말고, 시스템 메시지를 보내라
5. 도구를 바꾸지 말고, 도구로 상태 전환을 모델링하라
6. 도구를 제거하지 말고, defer_loading으로 스텁을 보내라
7. 모델을 바꾸려면 서브에이전트를 쓰라
8. 캐시 히트율을 uptime처럼 모니터링하라
PART 3. Compaction의 함정과 해결
9. Compaction에서 캐시가 깨지는 이유
10. Fork는 부모의 Prefix를 공유해야 한다
11. Server-side Compaction API
PART 4. MCP 도구와 Tool Search
12. MCP 도구의 컨텍스트 오염 문제
13. Tool Search의 작동 원리
14. Tool Search 설정과 최적화
PART 5. Claude Code의 컨텍스트 구조
15. /context 출력 분석
16. 캐싱 구조로 매핑하기
PART 6. 정리
17. 설계 원칙 요약
18. 실전 체크리스트
Claude Code처럼 긴 대화를 이어가는 에이전트 제품은, 사용자가 메시지를 보낼 때마다 전체 대화 히스토리를 API에 보내야 합니다. 시스템 프롬프트, 도구 정의, 이전 대화, 도구 실행 결과 등이 모두 포함됩니다.
프롬프트 캐싱이 없다면, 매 요청마다 수만~수십만 토큰을 처음부터 다시 계산합니다. 대화가 길어질수록 비용과 지연 시간이 선형으로 증가합니다.
매 턴마다 보내는 요청의 대부분은 동일합니다. 시스템 프롬프트는 같고, 도구 정의도 같고, 이전 대화 히스토리도 마지막 메시지만 추가된 것뿐입니다. 이 "앞부분이 동일하다"는 특성을 활용하는 것이 프롬프트 캐싱입니다.
프롬프트 캐싱은 이전 요청에서 이미 처리한 부분의 KV cache를 저장해두고, 동일한 prefix가 들어오면 재계산 없이 재사용합니다.
캐시에 쓰기(write)는 기본 입력 토큰 가격의 125%이지만, 캐시에서 읽기(read)는 기본 가격의 10%에 불과합니다. 한 번 캐시에 쓰면 이후 읽기에서 90% 할인된 가격으로 동작합니다. 기본 캐시 TTL은 5분이며, 캐시된 콘텐츠가 사용될 때마다 추가 비용 없이 갱신됩니다.
Claude Code 팀은 캐시 히트율을 uptime처럼 모니터링하고, 캐시가 깨지면 SEV(심각 인시던트)를 선언합니다. 캐시 히트율이 높을수록 비용이 줄어들고, 구독 플랜 사용자에게 더 넉넉한 rate limit을 제공할 수 있기 때문입니다.
프롬프트 캐싱은 prefix matching으로 작동합니다. API는 요청의 앞부분부터 cache_control 브레이크포인트까지를 캐싱합니다. 두 요청이 앞에서부터 동일한 내용을 공유할수록 캐시 히트가 발생합니다.
책에 비유하면, 책의 앞부분이 똑같으면 그 부분은 다시 읽지 않아도 되는 것과 같습니다. 하지만 중간에 한 글자라도 바뀌면 그 이후 전부가 캐시 무효화됩니다.
Claude Code가 API에 보내는 요청은 다음 순서로 구성됩니다.
| 순서 | 영역 | 변경 빈도 | 캐시 공유 범위 |
|---|---|---|---|
| 1 | System Prompt (시스템 프롬프트) | 거의 없음 | 모든 사용자/세션 |
| 2 | Tool Definitions (도구 정의) | 거의 없음 | 모든 사용자/세션 |
| 3 | Memory / Skills / Agents | 프로젝트별 | 같은 프로젝트 내 |
| 4 | Messages (대화 히스토리) | 매 턴 | 현재 세션만 |
위에서 아래로 갈수록 변경 빈도가 높아집니다. 정적 콘텐츠를 앞에 배치하여 최대한 많은 요청이 같은 prefix를 공유하게 만드는 것이 핵심입니다.
prefix의 어느 위치에서든 변경이 발생하면, 그 이후의 모든 캐시가 무효화됩니다. Thariq이 공유한 실제 캐시 브레이크 사례들은 다음과 같습니다.
tool_choice 설정이 호출 간에 달라짐모두 prefix의 일부가 바뀌는 것이므로, 그 이후 전체 캐시가 무효화됩니다.
프롬프트 캐싱에서 가장 중요한 원칙은 순서입니다. 여러 요청이 공유하는 prefix가 길수록 캐시 히트율이 높아집니다. Claude Code의 요청 구조는 이를 반영합니다.
[System Prompt] → [Tool Definitions] → [Memory/Skills] → [Messages]
(모든 세션 공통) (모든 세션 공통) (프로젝트별) (매 턴 변화)
시스템 프롬프트와 도구 정의는 모든 세션에서 동일하므로, prefix의 가장 앞에 위치합니다. 이 부분이 캐시되면 수많은 세션이 동시에 캐시 히트를 얻습니다. 대화 히스토리는 매 턴마다 변하므로 가장 뒤에 위치합니다.
이 순서는 의외로 깨지기 쉽습니다. 시스템 프롬프트에 현재 시각을 넣으면, 모든 세션의 prefix가 달라져서 캐시를 전혀 공유할 수 없게 됩니다. 도구 정의의 순서를 배열이 아니라 Set으로 관리해서 매번 순서가 바뀌는 것도 같은 문제를 일으킵니다.
시간이 지나거나 사용자가 파일을 변경하면 시스템 프롬프트에 담긴 정보가 outdated될 수 있습니다. 직관적으로는 시스템 프롬프트를 업데이트하고 싶지만, 시스템 프롬프트는 prefix의 가장 앞에 있으므로 여기가 바뀌면 모든 캐시가 무효화됩니다.
대신 다음 턴에 시스템 메시지(system message)로 업데이트 정보를 전달합니다. 시스템 메시지는 대화 히스토리의 일부이므로 prefix의 뒤쪽에 위치합니다. 앞쪽의 시스템 프롬프트와 도구 정의는 그대로 유지되어 캐시가 보존됩니다.
기존 설정 파일을 매번 덮어쓰는 대신, 이벤트 로그를 append하는 방식과 같은 사고방식입니다. 원본은 건드리지 않고, 변경사항만 뒤에 추가합니다.
Claude Code에는 Plan Mode가 있습니다. 이 모드에서는 모델이 파일을 읽기만 하고 쓰지 않습니다. 직관적인 구현 방식은 "plan mode에 들어가면 읽기 전용 도구만 남기고 쓰기 도구를 제거"하는 것입니다.
하지만 도구 정의는 prefix의 일부입니다. 도구를 추가하거나 제거하면 prefix가 바뀌고, 전체 대화의 캐시가 깨집니다.
Claude Code의 해결책은 도구 세트를 항상 고정하고, EnterPlanMode와 ExitPlanMode를 도구 자체로 만든 것입니다. 모델이 이 도구를 호출하면 상태가 전환되지만, prefix에 포함된 도구 정의 목록은 변하지 않습니다.
// 직관적 접근 (캐시 깨짐)
if (planMode) {
tools = [ReadFile, Search, Grep] // 도구 세트 변경 → 캐시 무효화
} else {
tools = [ReadFile, WriteFile, Bash, ...]
}
// Claude Code 접근 (캐시 유지)
tools = [ReadFile, WriteFile, Bash, ..., EnterPlanMode, ExitPlanMode] // 항상 동일
// 모델이 EnterPlanMode를 호출하면 내부적으로 상태 전환
이 패턴의 핵심은 "도구 정의를 바꾸는 것"이 아니라, "도구를 통해 상태를 바꾸는 것"입니다.
Claude Code에는 수십 개의 MCP 도구가 로드될 수 있습니다. 모든 도구의 전체 스키마(이름, 설명, 파라미터 타입)를 매 요청에 포함하면 컨텍스트 비용이 큽니다. 그렇다고 현재 불필요한 도구를 제거하면 prefix가 바뀌어 캐시가 깨집니다.
도구의 전체 스키마 대신 도구 이름만 담긴 경량 스텁을 defer_loading: true와 함께 보냅니다. 모델이 특정 도구를 쓰고 싶으면 ToolSearch 도구를 통해 "발견"하고, 그때 전체 스키마가 로드됩니다.
{
"name": "github.createPullRequest",
"description": "Create a pull request",
"input_schema": { ... },
"defer_loading": true // 전체 스키마를 컨텍스트에 로드하지 않음
}
스텁은 항상 같은 순서로 존재하므로 prefix가 안정적으로 유지됩니다. 이것은 본질적으로 lazy loading 패턴입니다. 필요할 때만 리소스를 로드하되, 메타데이터(스텁)는 항상 동일하게 유지합니다.
Tool Search Tool은 deferred 도구를 초기 프롬프트에서 완전히 제외하기 때문에 프롬프트 캐싱을 깨뜨리지 않습니다. 검색으로 발견된 도구는 Claude가 검색한 이후에만 컨텍스트에 추가됩니다.
대화 중간에 모델을 전환하면 당연히 캐시가 깨집니다. 모델 정보도 요청의 일부이기 때문입니다.
Claude Code에서는 Opus가 Haiku에게 작업을 위임할 때 서브에이전트(subagent) 패턴을 사용합니다. Opus가 "핸드오프 메시지"를 준비하고, 별도의 컨텍스트에서 Haiku가 그 작업을 처리합니다. 메인 대화의 prefix는 건드리지 않습니다.
Claude Code의 Explore 에이전트가 이 방식을 사용합니다. 탐색적인 작업은 Haiku 서브에이전트에게 위임하고, 메인 대화에서는 Opus가 결과만 받아 이어갑니다.
API 응답에는 캐시 성능을 추적할 수 있는 필드가 있습니다.
cache_creation_input_tokens: 캐시에 새로 쓴 토큰 수cache_read_input_tokens: 캐시에서 읽은 토큰 수cache_read_input_tokens가 높을수록 캐시가 잘 작동하고 있다는 의미입니다. cache_creation_input_tokens가 예상보다 높다면 어딘가에서 캐시가 깨지고 있다는 신호입니다.
Claude Code 팀은 이 비율을 지속적으로 모니터링하고, 캐시 히트율이 떨어지면 경보를 발생시키고 인시던트로 처리합니다. 몇 퍼센트의 캐시 미스율 차이가 구독 플랜의 rate limit 정책에 영향을 미치기 때문입니다.
에이전트를 만들 때, 비용이 예상보다 높거나 응답 지연이 느리다면 캐시 히트율을 먼저 확인하는 것이 좋습니다. 대부분의 비용 문제는 캐시가 깨지는 것에서 시작됩니다.
Compaction은 컨텍스트 윈도우가 가득 찼을 때, 이전 대화를 요약하여 새로운 세션으로 이어가는 것입니다. Claude Code는 200K 토큰의 컨텍스트 윈도우를 사용하는데, 긴 코딩 세션에서는 도구 호출 결과와 파일 내용이 누적되어 이 한계에 도달할 수 있습니다.
요약을 생성하려면 전체 대화를 모델에 보내야 합니다. 순진한 구현은 이렇게 됩니다.
// 요약 전용 별도 API 호출
{
system: "다음 대화를 요약해주세요", // 다른 시스템 프롬프트
tools: [], // 도구 없음
messages: [전체 대화 히스토리]
}
이 요청은 메인 대화의 prefix(시스템 프롬프트 + 도구 정의)와 완전히 다릅니다. 이미 캐시된 내용을 전혀 재사용할 수 없으므로, 수만~수십만 토큰을 처음부터 다시 처리해야 합니다.
대화가 길수록 이 비용은 커집니다. 컨텍스트 윈도우가 가득 차서 compaction을 해야 하는 시점이라면, 대화 히스토리도 그만큼 길다는 뜻이기 때문입니다.
Thariq이 공유한 원칙은 이것입니다.
"Fork operations need to share the parent's prefix."
compaction이든 요약이든 스킬 실행이든, 사이드 연산을 할 때 메인 대화와 동일한 시스템 프롬프트 + 동일한 도구 세트를 그대로 사용한다.
// 메인 대화의 마지막 요청
{
system: [시스템 프롬프트],
tools: [도구 정의],
messages: [대화 히스토리, 사용자 메시지]
}
// Compaction 요청 (캐시 히트를 위해 동일한 prefix 사용)
{
system: [시스템 프롬프트], // 동일
tools: [도구 정의], // 동일
messages: [대화 히스토리, 요약 지시 메시지] // 마지막 메시지만 다름
}
API 입장에서 compaction 요청은 메인 대화의 마지막 요청과 거의 동일합니다. 같은 prefix, 같은 도구, 같은 히스토리를 공유하므로 캐시가 그대로 재사용되고, 새로 처리해야 하는 토큰은 요약 지시 프롬프트와 출력뿐입니다.
이 방식에는 compaction buffer라는 개념이 필요합니다. 컨텍스트 윈도우를 꽉 채우면 compaction 메시지와 요약 출력 토큰을 넣을 공간이 없습니다. 디스크를 100% 채우면 정리 유틸리티가 작동할 수 없는 것과 같습니다.
Claude Code는 컨텍스트 윈도우의 약 16.5%를 항상 예약해 둡니다. 이 공간은 일반 대화에서는 사용되지 않고, compaction이 필요할 때만 활용됩니다.
Claude Code 팀은 위의 패턴을 개발자들이 직접 구현하지 않아도 되도록, Compaction을 API에 직접 통합했습니다. 현재 compact_20260112 베타로 제공됩니다.
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
system=[{
"type": "text",
"text": "You are a helpful coding assistant...",
"cache_control": {"type": "ephemeral"} # 시스템 프롬프트 캐시를 분리
}],
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
| 기능 | 설명 |
|---|---|
| 자동 요약 | 컨텍스트 한계 도달 시 API가 자동으로 이전 대화를 요약. 별도 API 호출이 불필요하므로 prefix가 깨질 위험이 원천적으로 사라짐 |
| 시스템 프롬프트 캐시 분리 | cache_control 브레이크포인트를 시스템 프롬프트 끝에 추가하면, compaction이 발생해도 시스템 프롬프트의 캐시는 독립적으로 유지 |
| 커스텀 요약 지시 | instructions 파라미터로 요약 방식을 제어. 예: "코드 스니펫과 변수명을 보존하라" |
| pause_after_compaction | 요약 생성 후 API가 일시정지하고, 개발자가 추가 컨텍스트(최근 메시지 보존 등)를 삽입한 뒤 응답을 이어갈 수 있음 |
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
max_tokens=4096,
messages=messages,
context_management={
"edits": [{
"type": "compact_20260112",
"instructions": "Focus on preserving code snippets, variable names, and technical decisions.",
}]
},
)
기본 요약은 범용적으로 동작하지만, 코딩 에이전트라면 코드와 기술적 결정을 보존하도록 지시하는 것이 효과적입니다.
MCP 서버를 연결하면 각 서버의 모든 도구 스키마(이름, 설명, 파라미터)가 컨텍스트에 로드됩니다. 서버 하나의 도구 수가 수십 개인 경우가 흔하고, 여러 서버를 연결하면 대화를 시작하기도 전에 컨텍스트의 상당 부분이 도구 정의로 사라집니다.
| MCP 서버 | 도구 수 | 소비 토큰 (대략) |
|---|---|---|
| GitHub | 91개 | ~46,000 |
| Jira | 다수 | ~17,000 |
| Docker | 135개 | ~126,000 |
| 일반 5개 서버 조합 | 58개 | ~55,000 |
Anthropic 내부에서도 도구 정의에 134K 토큰이 소비되는 사례가 관측되었습니다. 200K 컨텍스트 윈도우의 67%입니다.
토큰 비용만이 문제가 아닙니다. 도구 정의가 30~50개를 넘어가면 모델의 도구 선택 정확도가 급격히 떨어집니다. 비슷한 이름의 도구가 많을수록 잘못된 도구를 선택하거나 파라미터를 잘못 전달하는 빈도가 높아집니다.
아이러니하게도, MCP 설정을 강력하게 만들수록 Claude의 성능이 나빠지는 역설이 발생합니다.
Claude Code v2.1.7부터 Tool Search가 도입되었습니다. MCP 도구 정의의 총 토큰이 컨텍스트 윈도우의 약 10%를 초과하면 자동으로 활성화됩니다. 별도 설정이 필요 없습니다.
1. 토큰 체크
세션 시작 시 모든 MCP 서버의 도구 스키마 총 토큰 수를 계산
2. 임계값 판단
총 도구 정의 > 컨텍스트 윈도우의 10% → Tool Search 활성화
3. 도구 지연
모든 MCP 도구가 defer_loading: true로 마킹
Claude에게는 MCPSearch 도구만 주어짐
4. 온디맨드 발견
사용자가 작업을 요청하면 Claude가 MCPSearch로 관련 도구 검색
필요한 도구의 전체 스키마만 로드한 뒤 실행
사용자 입장에서는 아무것도 달라지지 않습니다. "Jira에서 ENG-4521 이슈 가져와서 구현해줘"라고 말하면, Claude Code가 내부적으로 검색 → 로드 → 실행을 알아서 처리합니다.
Anthropic 내부 테스트 결과는 다음과 같습니다.
| 모델 | Tool Search 적용 전 | Tool Search 적용 후 |
|---|---|---|
| Opus 4 도구 선택 정확도 | 49% | 74% |
| Opus 4.5 도구 선택 정확도 | 79.5% | 88.1% |
| 토큰 사용량 감소 | - | ~85% |
도구가 많을수록 오히려 정확도가 올라가는 역설적인 결과입니다. 전체 도구 목록을 한꺼번에 보여주는 것보다, 관련 도구만 검색해서 보여주는 것이 모델의 선택 정확도를 높여줍니다.
Tool Search는 자동으로 작동하지만, 필요에 따라 튜닝할 수 있습니다.
| 설정 | 방법 | 용도 |
|---|---|---|
| 임계값 변경 | ENABLE_TOOL_SEARCH=auto:15 | 자동 활성화 기준을 15%로 변경 |
| 특정 도구 즉시 로드 | defer_loading: false (도구별 개별 설정) | 매 세션 필수 도구를 항상 로드 |
| 비활성화 | MCPSearch를 disallowedTools에 추가 | 기존 방식(전체 로드)으로 복원 |
| 서버 인스트럭션 최적화 | serverInstructions 필드에 명확한 설명 작성 | 도구 검색 정확도 향상 |
Claude Code가 아니라 API를 직접 사용하여 에이전트를 만들 때는 defer_loading을 명시적으로 설정해야 합니다.
{
"type": "mcp_toolset",
"mcp_server_name": "github",
"default_config": { "defer_loading": true },
"configs": {
"search_files": { "defer_loading": false }
}
}
이 설정은 GitHub MCP 서버의 모든 도구를 기본적으로 지연 로드하되, search_files 도구만 항상 즉시 로드합니다. 매 세션마다 반드시 사용하는 도구가 있다면 이렇게 개별 설정하는 것이 효과적입니다.
Tool Search가 활성화되면, Claude가 도구를 "발견"하는 데 서버의 serverInstructions 필드를 참고합니다.
{
"mcpServers": {
"my-db-server": {
"command": "node",
"args": ["/path/to/server.js"],
"serverInstructions": "Database operations for PostgreSQL including queries, schema management, and data migrations."
}
}
}
도구의 description과 서버 인스트럭션이 명확하고 키워드가 풍부할수록 검색 정확도가 높아집니다. MCP 서버를 직접 만들거나 운영한다면, 도구 설명을 가능한 한 구체적으로 작성하는 것이 중요합니다.
Claude Code에서 /context 명령을 실행하면 현재 세션의 컨텍스트 윈도우가 어떤 구성 요소로 채워져 있는지 확인할 수 있습니다. 실제 출력 예시를 기반으로 각 카테고리의 역할을 정리합니다.
| 카테고리 | 예시 사용량 | 역할 | 캐시 특성 |
|---|---|---|---|
| System Prompt | ~3.4k (1.7%) | Claude Code의 기본 행동 규칙과 역할 정의. 모든 세션/사용자에게 동일 | 정적. 모든 세션이 캐시 공유 가능 |
| System Tools | ~17k (8.5%) | View, Edit, Bash, Grep 등 내장 도구 정의. MCP 도구는 Tool Search 시 별도 관리 | 정적. prefix에서 시스템 프롬프트 바로 뒤 |
| Custom Agents | ~75 (0.0%) | 사용자 정의 서브에이전트의 설명 | 반정적. 세션 시작 시 고정 |
| Memory Files | ~920 (0.5%) | CLAUDE.md 파일 내용. 프로젝트 컨벤션, 아키텍처 결정 등 | 반정적. 같은 프로젝트 내 공유 |
| Skills | ~454 (0.2%) | 재사용 가능한 작업 패턴 정의 | 반정적. 같은 프로젝트 내 공유 |
| Messages | ~19.6k (9.8%) | 현재 세션의 대화 히스토리. 사용자 입력, 응답, 도구 결과 등 | 동적. 매 턴마다 성장 |
| Free Space | ~125k (62.7%) | 새 메시지, 도구 결과, 파일 읽기 등에 사용 가능한 남은 공간 | 작업 가용 공간 |
| Autocompact Buffer | ~33k (16.5%) | Compaction 작업을 위해 예약된 공간. 요약 지시 + 출력 토큰용 | 비상 예약 공간 |
Autocompact Buffer는 PART 3에서 다룬 compaction buffer와 정확히 대응됩니다. 컨텍스트 윈도우의 ~16.5%를 항상 예약하여, 컨텍스트가 가득 찼을 때 compaction을 수행할 공간을 확보합니다. 이 공간이 없으면 compaction 자체를 수행할 수 없어 세션이 더 이상 이어질 수 없게 됩니다.
Free Space(~125k)가 "실제 작업에 쓸 수 있는 공간"이고, Autocompact Buffer(~33k)는 "비상 공간"으로 잠겨 있는 셈입니다.
[캐시 공유 가능 — 모든 세션 공통]
├── System Prompt (3.4k)
└── System Tools (17k)
[캐시 공유 가능 — 같은 프로젝트 내]
├── Custom Agents (75)
├── Memory Files (920)
└── Skills (454)
[동적 — 매 턴마다 성장]
└── Messages (19.6k)
[예약 공간]
├── Free Space (125k) ← 작업용
└── Autocompact Buffer (33k) ← compaction 전용
위에서 아래로 갈수록 변경 빈도가 높아지고, Thariq이 설명한 prefix 순서와 정확히 일치합니다. 정적 콘텐츠가 앞에 있어서 캐시 히트율이 최대화되는 구조입니다.
MCP 서버를 연결하면 System Tools 영역이 크게 늘어날 수 있습니다. 여러 MCP 서버를 연결한 상태에서 /context를 확인하면 System Tools가 수만 토큰을 소비하는 것을 볼 수 있습니다. 이때 Tool Search가 자동으로 활성화되면서 이 토큰 증가를 억제합니다. MCP 연결 전후로 /context를 비교해 보면 defer_loading의 효과를 직접 확인할 수 있습니다.
프롬프트 캐싱은 prefix match다. prefix의 어디든 변경이 생기면 그 이후 전부 무효화된다.
순서를 올바르게 잡으면 캐싱의 대부분이 자동으로 작동한다. 정적 → 동적 순서를 지키는 것만으로 대부분의 캐싱이 해결된다.
시스템 프롬프트 변경 대신 시스템 메시지를 사용하라. prefix의 앞쪽을 건드리지 않아야 캐시가 보존된다.
도구나 모델을 대화 중간에 바꾸지 말라. 상태 전환은 도구를 추가/제거하는 대신, 도구 호출로 모델링한다.
도구 제거 대신 defer_loading을 사용하라. 경량 스텁으로 prefix를 안정시키고, 필요한 도구만 온디맨드로 로드한다.
Fork 연산(compaction 등)은 부모의 prefix를 공유해야 한다. 사이드 연산에서도 동일한 시스템 프롬프트와 도구 세트를 사용하여 캐시를 재활용한다.
캐시 히트율을 uptime처럼 모니터링하라. cache_read_input_tokens와 cache_creation_input_tokens 비율을 추적하고, 이상 징후에 대응한다.
| 항목 | 확인 사항 | 위반 시 영향 |
|---|---|---|
| Prefix 순서 | 시스템 프롬프트 → 도구 정의 → 대화 히스토리 순서가 지켜지는가? | 전체 캐시 미스 |
| 시스템 프롬프트 불변성 | 타임스탬프, 동적 값이 시스템 프롬프트에 포함되어 있지 않은가? | 세션 간 캐시 공유 불가 |
| 도구 정의 안정성 | 도구 순서가 결정적인가? 도구 추가/제거가 대화 중간에 발생하지 않는가? | 대화 전체 캐시 무효화 |
| Compaction 설계 | Fork가 부모 prefix를 공유하는가? Compaction buffer가 확보되어 있는가? | 요약 시 비용 폭증 |
| MCP 도구 관리 | Tool Search가 활성화되어 있는가? 서버 인스트럭션이 충분한가? | 컨텍스트 50-70% 낭비 |
| 모니터링 | cache_read vs cache_creation 비율을 추적하는가? | 비용/지연 문제 사후 발견 |