프롬프팅
verified · type: reference · verified: 2026-08 · review: 30d · updated: 2026-08-09 · [prompting, api, cost-optimization]

프롬프트 캐싱

프롬프트의 안정적 프리픽스를 캐시해 반복 호출 시 재처리를 건너뛴다. 반복 컨텍스트가 큰 워크로드에서 입력 비용을 크게 줄이는 1순위 레버다.

모든 캐싱을 지배하는 한 규칙: 안정적인 것 먼저, 변하는 것 나중에 (stable first, variable last).

캐싱은 프리픽스 일치다. 프리픽스의 한 바이트라도 바뀌면 그 뒤가 전부 무효화된다. 이 한 문장에서 나머지가 전부 따라 나온다.


프로바이더별 메커니즘 (verified 2026-07)

프로바이더 방식 할인
Anthropic [HIGH] 명시적 cache_control 브레이크포인트 읽기 0.1× · 쓰기 1.25×(5분 TTL) / 2.0×(1시간 TTL)
OpenAI [official] ≥1,024 토큰 프리픽스 자동 (GPT-5.6+ 는 명시적 breakpoint 도 지원) 읽기 ~90% off · 쓰기 1.25×(GPT-5.6+)
Gemini [official] 암묵적 캐싱 기본 ON(2.5+) + 명시적 캐싱 · ≥2,048~4,096 토큰(모델별) 캐시 입력 ~90% off + 저장 $1/1M·시간

손익분기 (Anthropic 기준): 5분 TTL 은 2회 요청이면 이득(1.25× + 0.1× = 1.35× vs 2×). 1시간 TTL 은 쓰기가 2× 라 최소 3회는 읽어야 본전이다. 트래픽이 뜸하게 몰리는 패턴에만 1시간을 써라.


배치 순서

그림 — 프리픽스가 같아야 캐시가 산다
요청 ①
시스템도구 정의히스토리질문 A
요청 ② — 앞이 같으면 민트 구간은 캐시 적중
시스템도구 정의히스토리질문 B
요청 ③ — 앞쪽 하나가 바뀌면
시스템도구 정의 ✎히스토리질문 B
캐시는 왼쪽부터 이어진 만큼만 적중한다 — 바뀐 지점(✎) 뒤는 전부 재계산이다. 그래서 안 변하는 것(시스템·도구)을 앞에, 자주 변하는 것(질문)을 뒤에 둔다.
[ 툴 정의            ]  ← 렌더 순서상 맨 앞   ┐
[ 시스템 프롬프트     ]  ← 가장 안정적         │ 캐시 가능 프리픽스
[ 긴 정적 컨텍스트    ]  ← 안정                │
[ 천천히 바뀌는 문서  ]  ← 반(半)안정          ┘
[ 현재 사용자 메시지  ]  ← 가장 변동   ← 이 뒤는 캐시 안 됨

렌더 순서는 toolssystemmessages. 마지막 system 블록에 브레이크포인트를 걸면 툴과 시스템이 함께 캐시된다.

response = client.messages.create(
    model="claude-opus-5", max_tokens=16000,
    system=[{
        "type": "text", "text": large_document,
        "cache_control": {"type": "ephemeral"},   # 또는 {"type":"ephemeral","ttl":"1h"}
    }],
    messages=[{"role": "user", "content": "요약해줘"}],
)

브레이크포인트는 최대 4개. 세밀한 배치가 필요 없으면 최상위 cache_control 하나로 마지막 캐시 가능 블록에 자동 배치시켜도 된다.

최소 캐시 프리픽스는 모델마다 다르고 단조증가가 아니다 (verified 2026-08). 이걸 모르면 마커를 달았는데 조용히 캐시가 안 된다 — 에러도 안 난다:

최소 토큰 모델
512 Opus 5 · Fable 5 · Mythos 5
1024 Opus 4.8 · Sonnet 5 · Sonnet 4.6 · Sonnet 4.5
2048 Opus 4.7
4096 Opus 4.6 · Opus 4.5 · Haiku 4.5

3K 토큰 프롬프트는 Opus 5 에선 캐시되고 Opus 4.6 에선 조용히 안 된다.


무엇이 무엇을 무효화하나 (verified 2026-08) [HIGH]

캐시는 3계층이고, 변경은 자기 계층과 그 아래만 무효화한다. 이걸 알면 과잉 걱정을 줄일 수 있다.

바꾼 것 툴 캐시 시스템 캐시 메시지 캐시
툴 정의 추가·삭제·순서변경
모델 교체
시스템 프롬프트 내용
tool_choice, 이미지, thinking on/off
메시지 내용

tool_choice 를 요청마다 바꾸거나 thinking 을 껐다 켜도 툴+시스템 캐시는 살아 있다. 전면 재구축을 부르는 건 툴 정의 변경과 모델 교체 두 가지뿐이다.

시스템 프롬프트를 안 깨고 지시를 주입하는 법

세션 중간에 운영자 지시가 생겼을 때 최상위 system 을 고치면 대화 전체 프리픽스가 날아간다. 대신 messages[] 안에 {"role": "system", ...} 메시지를 붙여라 — 캐시된 히스토리 뒤에 놓이므로 프리픽스가 살아남는다. 베타 헤더 불필요.

지원: Opus 5 · Opus 4.8 · Fable 5 · Mythos 5. Sonnet 5 는 미지원 (400). 미지원 모델에선 user 턴 안의 <system-reminder> 텍스트로 대체한다.


조용한 무효화 범인들

프리픽스에 들어가는 코드에서 이걸 찾아라. 전부 에러 없이 캐시만 죽인다.

패턴 왜 깨지나
시스템 프롬프트의 datetime.now() / Date.now() 매 요청 프리픽스가 달라짐
앞쪽에 박힌 uuid4() · 요청 ID 같은 이유
sort_keys=True 없는 json.dumps · set 순회 직렬화 순서가 비결정적
시스템 프롬프트에 세션/유저 ID 보간 유저별 프리픽스 — 공유 불가
조건부 시스템 섹션 (if flag: system += ...) 플래그 조합마다 별개 프리픽스
유저별로 달라지는 툴셋 툴은 위치 0 — 아무것도 공유 안 됨

히트 확인하는 법

필드 의미
usage.cache_creation_input_tokens 이번에 캐시에 쓴 토큰 (1.25× 지불)
usage.cache_read_input_tokens 캐시에서 읽은 토큰 (0.1× 지불)
usage.input_tokens 캐시 안 된 나머지만

⚠️ input_tokens 는 전체가 아니라 잔여분이다. 총 프롬프트 크기 = 세 값의 합. 에이전트를 몇 시간 돌렸는데 input_tokens 가 4K 로 보인다면 나머지는 캐시에서 온 것이다 — 합을 봐라.

동일 프리픽스 반복 요청에서 cache_read_input_tokens 가 계속 0 이면 위 표의 범인이 있다. 히트율이 70% 아래로 떨어지면 프롬프트 드리프트 경보로 삼아라.


함정

  • 20블록 룩백: 브레이크포인트는 뒤로 최대 20개 콘텐츠 블록만 훑어 이전 캐시를 찾는다. 툴 호출이 많은 에이전트 루프에서 한 턴에 20블록을 넘기면 다음 요청이 조용히 미스난다. 긴 턴에선 ~15블록마다 브레이크포인트를 추가하라.
  • 동시 요청: 캐시는 첫 응답이 스트리밍을 시작한 뒤에야 읽을 수 있다. 같은 프리픽스로 N개를 동시에 쏘면 전부 제값을 낸다. 1개를 먼저 보내 첫 토큰을 받은 뒤 나머지를 쏴라.
  • 포크 연산: 요약·압축·서브에이전트가 별도 호출을 만들 때 system·tools·model 을 조금이라도 다르게 재조립하면 부모 캐시를 통째로 놓친다. 그대로 복사하고 뒤에만 덧붙여라.
  • 프리워밍: max_tokens: 0 요청은 프리필만 돌고 즉시 반환한다(출력 토큰 과금 없음). 앱 기동 시 캐시를 미리 데워 첫 요청 지연을 없앨 수 있다. 단 트래픽이 TTL 안에 계속 들어오는 서비스라면 불필요한 쓰기 비용일 뿐이다.
  • 캐시는 모델별이다. 모델을 바꾸면 우회로가 없다. 메인 루프는 한 모델로 고정하고 싼 작업은 서브에이전트로 분리하라.

참고

출처: Anthropic 메커니즘·무효화 계층·모델별 최소 길이는 first-party [HIGH] (verified 2026-08). OpenAI·Gemini 는 각 사 공식 문서 재확인 [official] (verified 2026-07) — 정확 할인율은 일부 미공개라 근사치. 원본 → 2026-07-25-anthropic-claude-deep