🔥 고급2026-07-045~7분
Prompt Caching 캐시 무효화 전략: TTL·버전 해시·비용 함정
Anthropic의 prompt caching은 잘못 설계하면 캐시 히트율이 20% 미만으로 떨어진다. 캐시 경계 설계, 버전 해시 관리, 비용 모니터링 루프를 함께 구성해야 실제 절감이 발생한다.
prompt-cachingcost-optimizationobservability
캐시 히트율이 낮은 이유
prompt caching은 cache_control: {type: 'ephemeral'} 마커 이전까지의 토큰이 동일할 때만 히트한다. 흔한 실패 패턴은 세 가지다.
- 시스템 프롬프트 앞에 동적 값 삽입 — 날짜, 요청 ID, 사용자 이름이 캐시 prefix를 매번 바꾼다.
- 캐시 경계를 너무 짧게 설정 — 최소 1,024 토큰(Claude 3.5) 미만 구간에 마커를 두면 캐싱 자체가 작동하지 않는다.
- 모델 버전 불일치 —
claude-3-5-sonnet-20241022와claude-3-5-sonnet-20240620은 캐시를 공유하지 않는다.
버전 해시 기반 캐시 경계 설계
정적 컨텍스트(시스템 프롬프트, RAG 청크, 도구 스키마)를 별도 모듈로 분리하고 SHA-256 앞 8자리를 버전 키로 관리한다. 버전이 바뀔 때만 캐시가 무효화되므로, 동적 값은 반드시 마커 이후 사용자 메시지 블록에 위치시킨다.
import anthropic, hashlib
client = anthropic.Anthropic()
STATIC_SYSTEM = """당신은 결제 도메인 전문 어시스턴트입니다.
[...약 1200 토큰 분량의 정책 문서...]"""
_version = hashlib.sha256(STATIC_SYSTEM.encode()).hexdigest()[:8] # e.g. 'a3f9c12b'
def call_with_cache(user_message: str) -> dict:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": STATIC_SYSTEM,
"cache_control": {"type": "ephemeral"}, # 경계 설정
}
],
messages=[{"role": "user", "content": user_message}],
)
usage = response.usage
hit = usage.cache_read_input_tokens > 0
print(f"[cache_version={_version}] hit={hit} "
f"write={usage.cache_creation_input_tokens} "
f"read={usage.cache_read_input_tokens}")
return {"hit": hit, "response": response}
캐시 TTL은 5분으로 고정되어 있다(Anthropic 공식). 트래픽이 드문 배치 파이프라인에서는 5분 내 재사용이 보장되지 않으므로, caching보다 Batch API가 더 경제적이다.
비용 모니터링 루프와 운영 체크리스트
캐시 히트 토큰은 일반 입력의 10% 비용, 캐시 생성 토큰은 125% 비용이 부과된다. 히트율이 낮으면 캐시 생성 비용만 늘어나는 역효과가 발생한다.
손익분기 계산: 캐시 생성 1회 비용 = 1.25×N 토큰. 동일 prefix 재사용 횟수 K에서 절감 = K×0.9×N. K ≥ 2 이상이어야 흑자다.
운영 체크리스트
- [ ] 시스템 프롬프트에 날짜·UUID 등 동적 값 포함 여부 확인
- [ ] 캐시 경계 이전 토큰 수 ≥ 1,024 검증
- [ ]
cache_read_input_tokens / (cache_read + cache_creation)히트율 주 1회 측정 - [ ] 히트율 < 40%이면 캐시 경계 위치 재검토
- [ ] 모델 버전 핀 고정 (
model파라미터 하드코딩, alias 사용 금지) - [ ] 저트래픽 파이프라인은 Batch API 전환 여부 비교