Claude Code의 Prompt Cache 버그 (v2.1.69~v2.1.89)

Claude Code v2.1.69~v2.1.89에서 발생한 Prompt Cache 버그의 원인, 영향 범위, 비용 영향을 정리합니다.

2026년 3월 초부터 약 한 달간 Claude Code에 Prompt Cache가 제대로 작동하지 않는 버그가 있었습니다. Claude Code 토큰 비용과 프롬프트 캐싱에서 정리했듯이 Prompt Caching은 입력 토큰 비용을 90%까지 절약하는 핵심 수단인데, 이 캐시가 작동하지 않으면 비용이 크게 증가합니다. 이 글에서는 해당 기간에 발생한 캐시 버그의 원인과 영향을 정리합니다.

1. 버그 요약

항목 내용

영향 버전

v2.1.69 (2026-03-05) ~ v2.1.89

수정 버전

v2.1.90 (2026-04-01)

근본 원인

v2.1.69에서 도입된 deferred_tools_delta`로 인해 resume 시 `messages[0] 구조가 새 세션과 달라짐

영향 대상

--resume 또는 `/resume`으로 세션을 재개하는 사용자

GitHub Issue

#34629, #28899

2. 원인: Resume 시 메시지 구조 불일치

2.1. 근본 원인

v2.1.69에서 도입된 deferred_tools_delta 기능이 원인입니다. 이 기능은 deferred tools 목록, MCP 서버 설정, skills 정보를 메시지에 첨부하는 방식을 변경했는데, 새 세션과 재개 세션에서 `messages[0]`의 구조가 달라지는 문제가 생겼습니다.

세션 유형 messages[0] 내용 크기

새 세션

deferred tools 목록, MCP 설정, skills, 날짜 컨텍스트

~13.4KB

재개 세션

날짜 컨텍스트만 포함 (나머지는 messages 끝에 추가)

~352B

Prompt Cache는 prefix의 해시값으로 캐시를 조회합니다. `messages[0]`의 내용이 13.4KB에서 352B로 바뀌면 해시값이 완전히 달라지므로, 이전 세션에서 쌓은 캐시를 전혀 재사용할 수 없었습니다.

2.2. MCP 서버, deferred tools와의 관계

이 버그는 MCP 서버나 deferred tools를 사용하는 환경에서 더 큰 영향을 받았습니다. 다만 이것은 MCP 서버의 tool schema가 불안정해서가 아니라, deferred tools/MCP 설정/skills 정보가 resume 시 `messages[0]`이 아닌 다른 위치에 배치되어 prefix가 달라지기 때문입니다. MCP 서버가 매번 완전히 동일한 schema를 반환하더라도, resume만 하면 메시지 구조가 달라져서 캐시 미스가 발생했습니다.

v2.1.90의 수정 내용도 이를 뒷받침합니다.

Fixed --resume causing a full prompt-cache miss on the first request for users with deferred tools, MCP servers, or custom agents

2.3. 부수적 문제: 매 턴 tool schema 재직렬화

근본 원인과 별개로, Claude Code가 매 턴마다 MCP tool schema를 `JSON.stringify`로 재계산하여 캐시 키를 만드는 비효율도 있었습니다. 이것은 캐시 미스를 유발하는 직접적인 원인은 아니었지만 성능 오버헤드를 발생시켰고, v2.1.90에서 tool schema를 한 번만 계산하고 재사용하도록 개선되었습니다.

3. 영향 범위

이 버그는 --resume (CLI 플래그)과 /resume (슬래시 커맨드) 모두에 해당합니다. 두 방식 모두 세션 재개 시 동일한 메시지 구조 불일치가 발생하기 때문입니다.

단, Prompt Cache의 TTL이 5분이므로 실질적인 비용 손해가 발생하는 경우는 제한적입니다.

시나리오 영향

일반 연속 세션 (resume 없이)

영향 없음. `messages[0]`이 세션 내내 안정적으로 유지

5분 이내에 resume

캐시가 살아있어야 하는데 prefix 불일치로 캐시 미스 발생 → 비용 손해

5분 이후에 resume

어차피 TTL 만료로 캐시 소멸 → 버그와 무관하게 비용 동일

--print --resume 자동화

매 호출이 새 프로세스이므로 캐시를 전혀 재활용하지 못함 → 가장 큰 피해

4. 비용 영향

정상 상태에서는 캐시가 쌓이면서 턴이 진행될수록 메시지당 비용이 감소합니다.

정상 (v2.1.68):  메시지 1 → $0.15,  메시지 4 → $0.02 (캐시 적중률 증가)
버그 (v2.1.69+): 모든 메시지 → $0.35~0.40 (매번 전체 히스토리를 Cache Write)

--print --resume 워크플로우에서는 cache_read 토큰이 ~11,000(시스템 프롬프트 분량)에 머물고, cache_creation 토큰이 300,000 이상으로 치솟는 현상이 관찰되었습니다. 메시지당 약 20배의 비용 증가가 보고되었습니다.

5. 수정 내용 (v2.1.90)

v2.1.90 (2026-04-01)에서 다음과 같이 수정되었습니다.

  • 메시지 구조 정규화: 세션 재개 시 `messages[0]`에 deferred tools, MCP 설정, skills를 새 세션과 동일한 위치에 삽입하도록 변경

  • tool schema 재직렬화 제거: MCP tool schema를 한 번만 계산하고 캐시하여, 매 턴 `JSON.stringify`를 호출하지 않도록 성능 개선

현재 버전 확인:

claude --version

v2.1.90 이상이면 수정된 상태입니다.

6. 영향 받았는지 확인하는 방법

2026년 3월 5일~4월 1일 사이에 Claude Code를 사용했다면, 다음 방법으로 영향 여부를 확인할 수 있습니다.

6.1. Resume 사용 여부 확인

이 버그는 resume 시에만 발생하므로, 해당 기간에 resume을 사용했는지가 핵심입니다.

6.1.1. /resume (슬래시 커맨드) 확인

대화형 세션 안에서 `/resume`을 입력한 기록은 `~/.claude/history.jsonl`에 남습니다.

Claude Code 프롬프트
~/.claude/history.jsonl에서 2026년 3월 5일~4월 1일 사이의 /resume 기록을 찾아줘.
각 resume 시점에 대해, 같은 프로젝트의 ~/.claude/projects/ 아래 JSONL 세션 로그에서
직전 세션의 마지막 timestamp와의 시간 간격을 계산해줘.
5분 이내에 resume한 경우가 있는지 확인하고 싶어.

6.1.2. --resume (CLI 플래그) 확인

`claude --resume`처럼 CLI 인자로 실행한 경우는 `history.jsonl`에 기록되지 않습니다. 이 경우는 shell history에서 확인합니다.

bash 사용자
grep "claude.*--resume" ~/.bash_history
zsh 사용자
grep "claude.*--resume" ~/.zsh_history

bash는 기본적으로 명령 실행 시각을 기록하지 않으므로 [1], --resume 사용 여부만 확인할 수 있고 5분 간격 분석은 어렵습니다. zsh는 EXTENDED_HISTORY 옵션이 켜져 있으면 `~/.zsh_history`에 타임스탬프가 함께 기록됩니다.

--resume`을 주로 자동화 스크립트(--print --resume`)에서 사용했다면 해당 스크립트의 실행 로그를 확인하는 것이 더 정확합니다.

5분 이내에 resume한 기록이 없다면, Prompt Cache의 TTL(5분)이 만료된 후 재개한 것이므로 이 버그로 인한 추가 비용은 발생하지 않은 것입니다.

6.2. API 사용량 확인

Anthropic Console에서 해당 기간의 토큰 사용량을 확인합니다. 평소 대비 `cache_creation_input_tokens`가 비정상적으로 높고 `cache_read_input_tokens`가 낮다면 이 버그의 영향을 받았을 가능성이 있습니다.

6.3. 캐시 메트릭 모니터링

세션 중 API 응답의 캐시 관련 토큰을 확인합니다.

  • cache_creation_input_tokens: 대화가 진행될수록 감소해야 정상

  • cache_read_input_tokens: 대화가 진행될수록 증가해야 정상

버그 발생 시에는 `cache_read_input_tokens`가 낮은 값에 머물고, `cache_creation_input_tokens`가 계속 높게 유지됩니다.


1. HISTTIMEFORMAT`을 설정하면 `history 명령에서 시각이 표시되지만, ~/.bash_history 파일 자체에는 타임스탬프가 저장되지 않습니다.
Claude Code 비용 최적화를 위한 지표 수집