# AI 에이전트

세션 중간에 모델을 바꾸면 Claude 프롬프트 캐시는 얼마나 깨질까?

@Hong2026-10-14

이 글에 담긴 코드와 결과는 직접 실행해 측정한 값을 바탕으로 작성했습니다. 실측은 Hong과 팀원들이 진행했고, 그 결과를 바탕으로 AI가 글을 쓰고 Hong이 검토합니다.

실습 코드 내려받기

질문
Claude Code 세션 도중에 모델을 바꾸면 프롬프트 캐시가 깨져 비용이 늘까?
답
대화 3턴만 opus에서 sonnet으로 바꾸자 세 번 모두 대화 1만 토큰을 캐시에 다시 써서, 그 턴은 API 단가 환산 0.0417달러로 Opus로 계속한 턴의 11배였다.
조건
2026-10-12, Claude Code 2.1.295 claude -p, Opus 5.5(claude-opus-5-5), effort 기본 medium, 약 1만 토큰 재료, 조건마다 3회

환경

측정일
2026년 10월 12일
Claude Code
2.1.295, claude -p, 기본 --model opus(결과의 modelUsage에 찍힌 실제 ID는 claude-opus-5-5), effort는 모든 호출에 명시(기본 medium)
대조 모델
sonnet(claude-sonnet-5-5), haiku(claude-haiku-5-5)
반복
조건마다 3회
실행
Claude 구독 로그인, node v25.5.0, 플러그인·스킬·MCP·사용자 설정을 뺀 조합
비용
구독 호출을 API 단가로 환산한 추정치(실제 청구액 아님), 가격표는 2026년 10월 12일 확인
목차
  1. 캐시는 무엇을 다시 쓰나
  2. 실습 준비
  3. 실습 1: 아무것도 바꾸지 않으면
  4. 실습 2: 모델을 바꾸면, 그리고 돌아오면
  5. 실습 3: 긴 대화에서 Haiku로 바꾸면 싸질까
  6. 정리

이번 시간에는 Claude Code 세션 도중에 모델을 바꾸면 프롬프트 캐시가 깨져 비용이 늘어나는지를 claude -p로 측정하며 배워가는 시간입니다. 아무것도 바꾸지 않은 대화를 기준으로, 3턴만 Sonnet으로 바꾼 대화와 긴 대화에서 Haiku로 바꾼 턴의 캐시와 비용을 차례로 볼게요.

모든 조건을 세 번씩 돌렸어요. 서버 쪽 캐시 상태와 모델 응답이 비결정적이라, 다시 돌리면 숫자가 달라질 수 있습니다. --model opus가 가리키는 모델도 시간이 지나면 달라질 수 있어요.

캐시는 무엇을 다시 쓰나

프롬프트 캐시는 요청의 앞부분(접두부)이 이전 요청과 글자 하나까지 같을 때, 그 부분의 계산 결과를 서버에서 꺼내 써요. 비슷한 질문에 저장된 답을 돌려주는 시맨틱 캐시와는 다릅니다.

Claude Code 문서(How Claude Code uses prompt caching)는 요청 하나를 시스템 프롬프트와 도구 정의, CLAUDE.md 같은 프로젝트 맥락, 대화의 세 층으로 설명해요. 앞 층이 바뀌면 뒤 층은 내용이 같아도 전부 다시 써요.

문서에는 캐시가 모델마다 따로 있어서 모델을 바꾸면 내용이 같아도 처음부터 다시 처리한다고(캐시 무효화) 적혀 있습니다.

실습 준비

이 글의 명령은 모두 실습 코드의 claude-prompt-cache-invalidation/ 디렉터리에서 실행합니다.

  • run.sh: 시나리오별 실행 함수와 호출 조합 함수를 담은 진입점
  • run.mjs: claude 호출 래퍼(5분 제한, 결과 파일과 .meta.json 기록)
  • field.mjs: 결과 파일에서 필드 하나 출력
  • questions.txt: 턴마다 보내는 질문 5줄
  • doc/: 대화 재료 파일 3개와 SHA256SUMS
  • agg.mjs: 턴별 캐시 판정과 비용 집계
  • prices.json: 모델별 단가표

따라 하시려면 다음이 필요해요.

  • Claude Code 2.1.295(claude --version)
  • Claude 구독 로그인
  • node 18 이상(작성할 때는 v25.5.0)

실행 스크립트

./run.sh <시나리오> [회차...]는 회차를 생략하면 세 번씩 돌고, 작업 디렉터리를 LAB_ROOT(기본 /tmp/ccache-lab) 아래에 시나리오와 회차마다 새로 만듭니다. 결과는 out/ 아래에 쌓이고, node agg.mjs가 거기서 숫자를 뽑아요.

run.sh의 보조 함수 rid는 세션마다 다른 실행 ID를 만듭니다. 첫 메시지 첫 줄에 넣어서 회차끼리 대화 캐시를 나눠 쓰지 않게 해요.

각자 환경의 플러그인, 스킬, MCP 커넥터, 사용자 설정이 섞이면 시스템 프롬프트가 사람마다 달라서 숫자를 비교할 수 없어요. 그래서 이 글의 호출은 모두 run.sh 안의 셸 함수 cc(safe 조합)로 부르고, 쓰는 플래그는 다음과 같습니다.

  • --safe-mode: CLAUDE.md, 스킬, 플러그인, 훅, MCP 서버를 모두 끕니다. 그런데 사용자 ~/.claude/settings.json은 끄지 않아서, 거기에 모델별 effort 저장값이 있으면 --effort를 주지 않은 호출에 그 값이 들어가요. 그래서 모든 호출에 --setting-sources project(빈 디렉터리라 읽을 프로젝트 설정이 없음)를 붙여 사용자 설정을 막고, effort는 항상 플래그로 명시했습니다.
  • --tools "": 내장 도구를 모두 뺍니다. 도구가 없으니 safe 조합의 호출 하나는 API 요청 하나예요.

run.mjs는 claude 호출을 감싸는 Node 래퍼예요. 표준 입력을 그대로 넘기고, 표준 출력을 결과 파일에 쓰고, 시작·종료 시간을 같은 이름의 .meta.json에 남겨요.

재개는 첫 턴 결과의 session_id를 읽어 --resume <id>로 넘깁니다. 세션 기록이 디렉터리별로 저장되니까, 재개는 같은 디렉터리에서 해요.

대화 재료와 판정 규칙

대화 재료는 측정 당시 이 사이트의 Redis Cache Aside 글 본문 앞 19,963바이트예요(doc/doc10k.txt, sha256 563ae347…88331). 지금 글과는 다를 수 있어서, 측정에 쓴 사본을 실습 코드의 doc/에 넣어 두었어요. Opus 기준으로 약 1만 토큰입니다.

첫 턴에만 "실행 ID" 한 줄과 이 재료를 표준 입력으로 넣고, "위 글의 주제를 한 문장으로 답하라"고 물어요. 이어지는 턴은 재료 없이 "이 글에 나온 Redis 버전만 답하라"처럼 짧은 질문만 보냅니다.

claude -p --output-format json의 결과에서 캐시를 판단하는 데 쓰는 필드는 usage 아래에 있어요.

  • input_tokens: 캐시와 관계없이 처리한 입력 토큰입니다. 캐시를 읽거나 쓴 토큰은 여기에 들어가지 않아서, 이 글의 호출에서는 거의 항상 2였어요.
  • cache_read_input_tokens: 캐시에서 읽은 토큰입니다. 접두부가 이어졌다면 직전 요청 전체에 가까운 크기가 나와요.
  • cache_creation_input_tokens: 캐시에 새로 쓴 토큰입니다. 새로 붙은 질문과 답만큼이면 정상이고, 대화 전체만큼이면 앞부분이 어디선가 달라진 거예요.
  • cache_creation.ephemeral_1h_input_tokens, ephemeral_5m_input_tokens: 쓴 토큰이 1시간 캐시인지 5분 캐시인지입니다. 구독으로 쓰는 메인 대화는 1시간이에요.
  • total_cost_usd: 클라이언트가 API 단가로 계산한 추정치이고, --resume으로 이어 간 세션에서는 세션 전체의 누적값입니다.

그래서 이 글의 턴 비용은 total_cost_usd가 아니라, 그 턴의 usage에 가격표 단가를 곱해서 따로 계산했어요.

캐시가 유지됐는지는 다음 규칙으로 판정해요.

  • 판정값 W: 판정할 요청의 cache_creation_input_tokens + input_tokens.
  • 기준 D: 이어 가는 세션은 첫 턴의 W(재료가 처음 쓰인 크기, 약 1만 토큰). 새 세션끼리 비교하는 실습은 먼저 보낸 세션의 W.
  • W가 D의 30% 미만이면 "유지", 70% 이상이면 "깨짐", 그 사이면 "부분"입니다. 재료(1만 토큰)와 한 턴의 새 토큰(수백)의 차이가 커서, 실제로는 모든 결과가 양 끝에 놓였고 "부분"은 한 번도 나오지 않았어요.
  • 모델이 바뀐 턴은 D가 다른 모델의 토크나이저로 센 값이라 정확히 같은 기준은 아니에요. 그래도 같은 재료로 시작한 첫 턴의 쓰기가 Opus 9,995~9,998토큰, Sonnet 5.5 10,002~10,003토큰으로 차이가 작아서 판정에는 영향이 없습니다.

agg.mjs는 out/의 결과를 읽어 턴별 캐시 판정(W, D, 판정)과 턴 비용을 출력해요. 단가는 prices.json(가격표 값, 확인 날짜 포함)에서 읽고, 가격표(2026년 10월 12일 확인, 100만 토큰당 달러)는 이렇습니다.

  • Opus 5.5: 입력 4, 1시간 쓰기 8, 읽기 0.20, 출력 20
  • Sonnet 5.5: 입력 2, 1시간 쓰기 4, 읽기 0.10, 출력 10
  • Haiku 5.5: 요청의 입력 합(캐시 읽기·쓰기 포함)이 10만 토큰 이하면 입력 0.10, 1시간 쓰기 0.20, 읽기 0.01, 출력 0.50. 10만 토큰을 넘으면 입력 0.50, 1시간 쓰기 1, 읽기 0.05, 출력 2.50

여기서 눈여겨볼 건 Opus 5.5에서 1시간 캐시 쓰기가 읽기의 40배라는 점이에요. 그래서 대화가 길수록 "읽느냐 다시 쓰느냐"가 턴 비용을 거의 다 정합니다.

출력 줄의 열은 왼쪽부터 세션·회차·턴, 그 턴의 모델, cache_read, cache_creation(괄호는 1시간·5분), 출력 토큰, W와 D와 판정, 그 턴의 비용(API 단가 환산 추정치)이에요.

실습 1: 아무것도 바꾸지 않으면

먼저 기준부터 잡아 볼게요. 네 턴 모두 --model opus --effort medium으로 같게 보냈어요.

run.sh의 flags가 시나리오와 턴 번호에 따라 플래그를 정하고, run_R이 첫 턴을 보낸 뒤 같은 디렉터리에서 --resume으로 2~4턴을 이어요. 실습 2의 R1은 flags의 해당 줄만 다릅니다.

chmod +x run.sh
./run.sh R0
node agg.mjs R | grep -E '^R0-r1|^  R0 '
R0-r1-t1       opus-5-5   read   1454 cw   9995(1h) out  174 | W   9997  | $0.0837
R0-r1-t2       opus-5-5   read  11081 cw    588(1h) out   26 | W    590 D 9997 유지 | $0.0074 | vs prev -368
R0-r1-t3       opus-5-5   read  11644 cw    101(1h) out   29 | W    103 D 9997 유지 | $0.0037 | vs prev -25
R0-r1-t4       opus-5-5   read  11720 cw    105(1h) out    5 | W    107 D 9997 유지 | $0.0033 | vs prev -25
  R0 t1            3회: 쓰기 3           read 1454 | creation 9995~9996 | out 134~174 | $0.0829~0.0837
  R0 t2            3회: 유지 3           read 11081~11082 | creation 548~588 | out 26 | $0.0071~0.0074
  R0 t3            3회: 유지 3           read 11605~11644 | creation 101 | out 29 | $0.0037~0.0037
  R0 t4            3회: 유지 3           read 11681~11720 | creation 105 | out 5 | $0.0033~0.0033

출력을 보면 2턴부터 대화 전체를 읽었고, 턴 비용은 첫 턴의 10분의 1 아래로 내려갔어요. 세 번 모두 같았습니다.

처음 보내는 첫 턴도 1,454토큰을 읽었는데, 다른 세션, 다른 디렉터리에서 먼저 쓴 시스템 프롬프트를 읽은 거예요. 그래서 "read가 0이 아니면 캐시가 유지된 것"으로 판정하면 틀려요.

vs prev는 이번 턴의 cache_read에서 직전 요청이 읽고 쓴 토큰의 합을 뺀 값이에요. 0이면 직전 요청 전체를 읽은 것이고, 음수면 그만큼 직전 요청의 끝부분을 다시 썼다는 뜻입니다. 1만 토큰 대화에서 수십~수백 토큰이라 판정은 "유지"예요.

실습 2: 모델을 바꾸면, 그리고 돌아오면

R1은 1, 2턴을 Opus로, 3턴만 --model sonnet, 4턴은 다시 --model opus로 보냈어요.

./run.sh R1
node agg.mjs R | grep -E '^R1-r1|^  R1 '
R1-r1-t1       opus-5-5   read   1454 cw   9995(1h) out  152 | W   9997  | $0.0833
R1-r1-t2       opus-5-5   read  11081 cw    566(1h) out   26 | W    568 D 9997 유지 | $0.0073 | vs prev -368
R1-r1-t3       sonnet-5-5 read   1454 cw  10325(1h) out   29 | W  10327 D 9997 깨짐 | $0.0417 | vs prev -10193
R1-r1-t4       opus-5-5   read  11622 cw    289(1h) out   37 | W    291 D 9997 유지 | $0.0054 | vs prev -157
  R1 t1            3회: 쓰기 3           read 1454 | creation 9995~9996 | out 135~163 | $0.0830~0.0835
  R1 t2            3회: 유지 3           read 11081~11082 | creation 549~577 | out 26 | $0.0071~0.0074
  R1 t3            3회: 깨짐 3           read 1454 | creation 10309~10337 | out 29 | $0.0417~0.0418
  R1 t4            3회: 유지 3           read 11606~11634 | creation 289 | out 11~37 | $0.0049~0.0054
  • 3턴(Sonnet 5.5)은 세 번 모두 "깨짐"이었습니다. 읽은 1,454토큰은 Sonnet 5.5의 시스템 프롬프트를 다른 세션이 먼저 써 둔 것이고, 대화는 처음부터 다시 썼어요.
  • 3턴 비용은 2 × 2 + 10,325 × 4 + 1,454 × 0.10 + 29 × 10 = 41,739(100만 토큰당 단위), 0.0417달러입니다. 거의 전부가 1시간 쓰기 단가 × 대화 길이예요.
  • 4턴은 Opus로 돌아오자 "유지"였습니다. 2턴까지의 대화로 쓴 Opus 캐시가 수명(1시간) 안이라 남아 있었고, 4턴은 그 뒤에 붙은 Sonnet 턴의 질문과 답(289토큰)만 새로 썼어요.

질문은 "PostgreSQL 버전만 답하라" 한 줄이었고 답은 29토큰이었는데, 이 턴의 0.0417달러는 아무것도 바꾸지 않은 실습 1의 3턴(0.0037달러)의 11배입니다. 단가가 절반인 모델로 바꾼 턴이 오히려 비싸진 거죠.

실습 3: 긴 대화에서 Haiku로 바꾸면 싸질까

Claude Code 팀이 쓴 "Lessons from building Claude Code: Prompt caching is everything"(이하 Lessons 글)은 Opus와 10만 토큰째 대화하고 있다면, Haiku로 바꾸는 것이 Opus가 답하는 것보다 비싸다고 써요.

그런데 가격표에서 Haiku 5.5의 1시간 쓰기 단가는 요청이 10만 토큰 이하일 때 0.20달러로 Opus 5.5의 읽기 단가와 같아요. 10만 토큰을 넘으면 1달러로 5배가 됩니다. 그럼 실제로는 어떨까요?

발행 글 여러 편을 이어 붙여 Haiku 요청의 입력 합이 약 8만 4천 토큰(doc85k.txt, 169,908바이트)과 약 11만 7천 토큰(doc120k.txt, 239,946바이트)이 되게 만들었어요. 회차마다 Opus로 첫 턴 하나를 쓰고, 같은 첫 턴에서 --resume <id> --fork-session으로 두 갈래를 냈습니다(run_H).

  • (b) --model haiku로 짧은 질문 하나
  • (a) --model opus로 같은 질문

--fork-session은 재개하되 새 세션 ID를 만드는 플래그라서, (b)를 먼저 돌려도 원 세션은 바뀌지 않아요. prompt는 그 요청의 입력 합(input + creation + read)이고, Haiku 요청에는 적용된 단가 구간을 붙였습니다.

./run.sh H
node agg.mjs H | grep -E '^H-[0-9]+k-r1|^  H'
H-85k-r1-t1    opus-5-5   read   1454 cw  82448(1h) out  832 | W  82450  | $0.6765 | prompt 83904
H-85k-r1-b     haiku-5-5  read    535 cw  84011(1h) out  828 | W  84013 D 82450 깨짐 | $0.0172 | prompt 84548 (<=100k)
H-85k-r1-a     opus-5-5   read  83902 cw    879(1h) out  432 | W    881 D 82450 유지 | $0.0325 | prompt 84783
H-120k-r1-t1   opus-5-5   read   1454 cw 114999(1h) out  797 | W 115001  | $0.9362 | prompt 116455
H-120k-r1-b    haiku-5-5  read   1454 cw 115608(1h) out   24 | W 115610 D 115001 깨짐 | $0.1157 | prompt 117064 (>100k)
H-120k-r1-a    opus-5-5   read 116453 cw    844(1h) out  506 | W    846 D 115001 유지 | $0.0402 | prompt 117299
  H-85k t1         3회: 쓰기 3           read 1454 | creation 82445~82448 | out 464~832 | $0.6692~0.6765
  H-85k b          3회: 깨짐 3           read 535~1454 | creation 82686~84011 | out 117~828 | $0.0166~0.0172
  H-85k a          3회: 유지 3           read 83899~83902 | creation 511~879 | out 284~432 | $0.0274~0.0325
  H-120k t1        3회: 쓰기 3           read 1454 | creation 114999 | out 384~797 | $0.9280~0.9362
  H-120k b         3회: 깨짐 3           read 1454 | creation 115247~115608 | out 11~851 | $0.1154~0.1174
  H-120k a         3회: 유지 3           read 116453 | creation 431~844 | out 266~506 | $0.0321~0.0402

Opus 갈래 (a)는 세 번 모두 첫 턴의 캐시를 읽었고, Haiku 갈래 (b)는 처음부터 다시 썼어요. 1회차의 턴 비용을 그대로 계산하면 이렇습니다(100만 토큰당 단가, 결과는 달러).

  • 85k, Haiku 전환: 2 × 0.10 + 84,011 × 0.20 + 535 × 0.01 + 828 × 0.50 = 17,222 → 0.0172
  • 85k, Opus 계속: 2 × 4 + 879 × 8 + 83,902 × 0.20 + 432 × 20 = 32,460 → 0.0325
  • 120k, Haiku 전환: 2 × 0.50 + 115,608 × 1 + 1,454 × 0.05 + 24 × 2.50 = 115,742 → 0.1157
  • 120k, Opus 계속: 2 × 4 + 844 × 8 + 116,453 × 0.20 + 506 × 20 = 40,171 → 0.0402

세 회차 모두 방향이 같았어요. 8만 4천 토큰에서는 Haiku로 바꾼 턴(0.0166~0.0172달러)이 Opus로 계속한 턴(0.0274~0.0325달러)보다 쌌고, 11만 7천 토큰에서는 Haiku로 바꾼 턴(0.1154~0.1174달러)이 Opus로 계속한 턴(0.0321~0.0402달러)의 약 3배였습니다.

10만 토큰 아래에서는 Haiku의 쓰기 단가와 Opus의 읽기 단가가 같아서 입력 쪽 비용이 비슷해요. 10만 토큰을 넘으면 Haiku 쪽 입력 단가가 5배로 뛰어서, 출력 차이로는 메울 수 없어요. Lessons 글의 "10만 토큰째면 Haiku가 더 비싸다"는 지금 가격표에서 8만 4천 토큰 대화에는 맞지 않았고, 11만 7천 토큰 대화에는 맞았습니다.

단, 이 비교는 그 한 턴의 비용이에요. Haiku로 바꾼 뒤 Haiku로 계속 이어 가면 다음 턴부터는 Haiku 캐시를 읽고, 다시 Opus로 돌아오면 Opus 캐시가 수명 안인지에 따라 비용이 달라집니다.

정리

범위: Claude Code 2.1.295의 claude -p, 2026년 10월 12일, 기본 --model opus(claude-opus-5-5)와 명시한 effort(기본 medium), 플러그인·스킬·MCP·사용자 설정을 뺀 조합, 약 1만 토큰 재료, 조건마다 3회, 금액은 API 단가 환산 추정치.

  • 같은 대화의 3턴만 --model sonnet으로 바꾸자 세 번 모두 대화 1만 토큰을 다시 써서 그 턴이 0.0417달러로 Opus로 계속한 턴(0.0037달러)의 11배였고, 4턴에 Opus로 돌아오자 Opus 캐시를 다시 읽었어요. 대화 도중에는 모델을 바꾸지 마시고, 바꿨다 돌아올 때는 원래 모델의 캐시가 수명 안인지부터 따져 보세요.
  • 대화 8만 4천 토큰에서 Haiku로 바꾼 턴은 0.0166~0.0172달러로 Opus로 계속한 턴(0.0274~0.0325달러)보다 쌌지만, 11만 7천 토큰에서는 0.1154~0.1174달러로 Opus 턴(0.0321~0.0402달러)의 약 3배였습니다. 대화가 10만 토큰을 넘었다면 싸게 하려고 Haiku로 바꾸지는 마세요.
  • 처음 보내는 대화도 다른 세션이 써 둔 시스템 프롬프트를 1,454토큰 읽었고, total_cost_usd는 재개한 세션의 누적값이었어요. 캐시 판정은 cache_read가 0인지가 아니라 cache_creation_input_tokens 크기로 하고, 턴 비용은 그 턴의 usage에 가격표 단가를 곱해 계산해 주세요.
내 링크 만들기