프롬프트 캐시 미스는 왜 사용량 지표가 아니라 요청 동등성 버그일까
캐시 히트율이 갑자기 0이 됐을 때, 우리는 비용 문제가 아니라 어떤 요청 조립 버그를 먼저 의심해야 할까?
프롬프트 캐시 미스는 왜 사용량 지표가 아니라 요청 동등성 버그일까
- 카테고리: ai_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: 캐시 히트율이 갑자기 0이 됐을 때, 우리는 비용 문제가 아니라 어떤 요청 조립 버그를 먼저 의심해야 할까?
- 핵심 출처:
- Prompt caching | OpenAI API - 게시일 미기재, 확인일 2026-07-27
- Changelog | OpenAI API - 2026-07-09 및 2026-07-22 항목, 확인일 2026-07-27
- Cache diagnostics | Claude Platform Docs - 베타 헤더 2026-04-07, 확인일 2026-07-27
- Context editing | Claude Platform Docs - 베타 헤더 2025-06-27, 확인일 2026-07-27
- Claude Platform release notes - 2026-07-24 Opus 5 및 2026-07-01 도구 변경 항목, 확인일 2026-07-27
1. 왜 지금 봐야 하나
LLM 앱에서 프롬프트 캐싱은 이제 “운 좋으면 할인되는 기능”보다 운영 설계에 가까워지고 있다. OpenAI의 2026년 7월 changelog는 GPT-5.6 계열에 explicit prompt caching controls가 추가됐다고 적고, 같은 prompt caching 문서는 GPT-5.6 이후 모델에서 캐시 쓰기 토큰이 cache_write_tokens로 보고되며 쓰기 비용이 uncached input의 1.25배라고 설명한다. 즉 캐시를 잘못 쓰면 절약이 아니라 추가 비용이 될 수 있다.
Anthropic 쪽도 방향은 비슷하다. Claude 문서는 prompt caching이 prefix가 byte-for-byte로 같을 때만 의미가 있다고 설명하고, cache diagnostics 베타는 이전 응답 id와 현재 요청을 비교해 system_changed, tools_changed, messages_changed 같은 캐시 미스 원인을 알려준다. release notes에는 2026년 7월 mid-conversation tool changes 베타가 “대화 중 도구를 추가·제거하면서도 prompt cache를 보존”하는 기능으로 소개되어 있다.
여기서 개발자에게 중요한 결론은 이것이다. 캐시 히트율이 낮다는 것은 단순한 인프라 운 문제가 아닐 수 있다. 대부분은 “우리가 매번 같은 prefix라고 믿은 요청이 사실은 같지 않았다”는 요청 동등성 버그다.
2. 핵심 개념
프롬프트 캐시는 결과 캐시가 아니다. 같은 질문에 같은 답을 저장해 두었다가 돌려주는 HTTP 캐시와 다르다. 모델은 여전히 새 출력을 생성한다. 다만 이전 요청에서 이미 계산한 prompt prefix의 KV 상태를 재사용해 prefill 비용과 지연을 줄인다.
따라서 캐시의 핵심 조건은 “의미가 비슷하다”가 아니라 렌더링된 요청 prefix가 동일하다이다. 다음 둘은 사람 눈에는 같은 시스템 프롬프트처럼 보일 수 있지만 캐시 입장에서는 다르다.
You are a helpful assistant. Today is 2026-07-27.
You are a helpful assistant. Today is 2026-07-28.
도구도 마찬가지다. 같은 도구 목록이라도 순서가 바뀌거나 JSON schema 직렬화 순서가 흔들리면 prefix가 바뀐다. 구조화 출력 schema, image detail, thinking 설정, context management 설정처럼 모델 입력으로 렌더링되는 파라미터도 캐시 동등성에 영향을 줄 수 있다.
운영 관점에서는 세 가지를 분리해야 한다.
- cacheability: 1024 토큰 이상처럼 캐시 대상이 될 수 있는가?
- equivalence: 이전 요청과 prefix가 실제로 같은가?
- availability/routing: 같은 prefix라도 아직 캐시가 남아 있고, 적절한 서버로 라우팅됐는가?
cached_tokens 또는 cache_read_input_tokens가 0이라는 사실만으로는 세 원인 중 무엇인지 모른다. 그래서 캐시 디버깅은 사용량 지표만 보는 일이 아니라 요청 조립 과정을 추적하는 일이 된다.
3. 최신 이슈와 연결
OpenAI의 최신 prompt caching 문서는 GPT-5.6 이후에 prompt_cache_key와 explicit breakpoint가 더 중요해졌다고 설명한다. prompt_cache_key는 같은 긴 prefix를 공유하는 요청을 같은 캐시 쪽으로 보내는 라우팅 힌트이고, explicit breakpoint는 “여기까지가 재사용 가능한 prefix”라고 표시하는 계약이다. 단, traffic per key를 대략 15 requests/minute 수준으로 관리하라는 지침도 함께 있다. 너무 넓은 key 하나에 모든 요청을 몰면 오히려 안정적인 캐시 설계가 아니다.
Anthropic의 cache diagnostics는 다른 각도에서 같은 문제를 푼다. 이전 응답 id를 넘기면 API가 현재 요청과 비교해 첫 divergence를 보고한다. 예를 들어:
system_changed: 시스템 프롬프트에 timestamp, request id, 실험 플래그가 섞였을 수 있다.tools_changed: 도구가 추가·삭제·재정렬됐거나 schema 직렬화가 비결정적일 수 있다.messages_changed: 과거 메시지를 append-only로 보존하지 않고 수정·삭제·재직렬화했을 수 있다.unavailable: model, tool_choice, thinking, context_management, beta header 같은 다른 prompt-affecting 파라미터가 달라졌을 수 있다.
Context editing 문서는 더 미묘한 트레이드오프를 보여준다. 오래된 tool result를 지우면 context를 아끼고 모델 focus를 높일 수 있지만, 지운 지점부터 캐시 prefix가 깨질 수 있다. thinking block을 보존하면 캐시 히트에는 유리하지만 context window를 더 차지한다. 반대로 thinking을 지우면 context 여유는 생기지만 cache가 무효화될 수 있다. 즉 context를 줄이는 최적화와 cache를 살리는 최적화는 항상 같은 방향이 아니다.
4. 개발자 관점 해석
프롬프트 캐시를 운영하려면 “프롬프트 문자열”이 아니라 프롬프트 빌드 파이프라인을 관리해야 한다.
첫째, stable prefix와 variable suffix를 코드 레벨에서 분리한다. 시스템 지침, 긴 문서, 도구 정의, 구조화 출력 schema, 예시는 앞에 둔다. 사용자 질문, 현재 시간, AB test id, request id, 개인화 데이터는 뒤로 보낸다. “오늘 날짜가 시스템 프롬프트에 있으면 모델이 더 잘 알겠지” 같은 습관은 캐시 관점에서는 prefix 오염이다.
둘째, 도구와 schema를 결정적으로 직렬화한다. JSON schema 객체를 매번 다른 key 순서로 만들거나, 사용 가능한 도구만 매번 tools 배열에 넣는 방식은 캐시를 쉽게 깨뜨린다. 가능하면 도구 목록은 고정 순서로 보내고, 실제로 허용할 도구는 별도 선택 파라미터나 런타임 정책으로 제한한다. 이 원칙은 도구 호출 품질뿐 아니라 캐시 hit rate에도 영향을 준다.
셋째, compaction/context editing은 캐시 비용과 함께 설계한다. 오래된 도구 결과를 조금씩 자주 지우면 매번 cache write가 발생할 수 있다. 반대로 아무것도 지우지 않으면 context window와 입력 비용이 커진다. 그래서 “언제 지울 것인가”는 토큰 수 기준만이 아니라 “얼마나 큰 prefix를 새로 쓰게 되는가”까지 포함해야 한다.
넷째, 캐시 지표를 순이익으로 본다. GPT-5.6 이후처럼 cache write 비용이 따로 보고되는 모델에서는 cached_tokens만 보면 안 된다. 최소한 다음을 같이 기록해야 한다.
cache_read_tokens
cache_write_tokens
uncached_input_tokens
TTFT
request_template_version
prompt_cache_key
breakpoint_count
first_cache_miss_reason(가능한 경우)
캐시는 성공하면 비용과 TTFT를 줄이지만, 잘못 설계하면 write 비용만 쌓이고 prefix 안정성 버그를 숨긴다.
5. 내 프로젝트에 적용할 체크포인트
- 시스템 프롬프트에 날짜, 사용자 이름, request id, 실험 flag 같은 동적 값이 들어가 있는가?
- tools 배열의 순서와 schema 직렬화가 매 요청마다 완전히 같은가?
- structured output schema를 요청마다 새로 생성하면서 key 순서가 흔들리지는 않는가?
- 긴 문서/RAG context를 캐시하려면 어느 block 뒤에 breakpoint를 둘지 명확한가?
prompt_cache_key가 너무 넓거나 너무 좁지 않은가? 같은 prefix를 공유하는 traffic 단위로 나뉘어 있는가?- 대화 history를 append-only로 보존하는가, 아니면 중간 메시지를 수정하거나 요약문으로 바꿔치기하는가?
- context editing이나 compaction이 실행될 때 cache miss와 cache write 비용이 함께 관측되는가?
- 캐시 미스를 “벤더 문제”로 보기 전에 요청 diff를 남길 수 있는가?
6. 오늘 10분 액션
오늘은 코드 수정까지 하지 않아도 된다. 현재 LLM 호출 하나를 골라 캐시 동등성 점검표를 만든다.
- 최근 요청 2개를 로그에서 고른다. 같은 기능, 같은 모델, 비슷한 길이의 요청이면 좋다.
- 모델에 보내기 직전의 “렌더링된 요청”을 저장했다고 가정하고, 다음 네 영역을 나눠 적는다.
- model/options
- system/developer instructions
- tools/schema/output format
- messages/context
- 각 영역 옆에 “매번 같아야 하는가?” 또는 “매번 달라도 되는가?”를 표시한다.
- 같아야 하는데 달라질 수 있는 항목 3개를 찾는다. 예: timestamp, schema key order, tool list filtering.
- 다음 배포에서 기록할 metric 이름을 정한다. 최소:
cached_tokens,cache_write_tokens,prompt_cache_key,template_version.
10분 뒤 남아야 하는 문장은 이것이다.
프롬프트 캐시 최적화는 캐시를 켜는 일이 아니라, 같은 prefix를 같은 prefix로 계속 보내는 요청 조립 계약을 지키는 일이다.
7. 더 볼 자료
- Prompt caching | OpenAI API
- Changelog | OpenAI API
- Cache diagnostics | Claude Platform Docs
- Context editing | Claude Platform Docs
- Claude Platform release notes
중복 회피 메모
로컬 content/generated와 Supabase 최근 ai_dev 글을 확인했다. 2026-06-18 글은 prompt caching을 “프롬프트 구조 계약”으로 설명했고, 이후 글들은 LLM 라우터의 prefix-cache-aware scheduling, 서비스 티어, token counting, context management, fine-grained tool streaming을 다뤘다. 이번 글은 일반적인 캐시 구조 설명을 반복하지 않고, 2026년 7월 OpenAI GPT-5.6의 explicit prompt caching·cache write 과금과 Anthropic cache diagnostics/context editing 문서를 바탕으로 캐시 미스를 요청 동등성 버그로 디버깅하는 방법에 집중한다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)