프롬프트 캐싱과 컨텍스트 캐싱(Prompt Caching and Context Caching)
시스템 프롬프트(system prompt)는 4,000 토큰(tokens)입니다. RAG 컨텍스트(context)는 20,000 토큰입니다. 두 가지 모두를 모든 요청(request)마다 함께 보내고, 매번 둘 다에 대해 비용을 지불합니다. 프롬프트 캐싱(prompt caching)은 제공자(provider)가 그 접두부(prefix)를 자기 쪽에 따뜻하게(warm) 유지하도록 하고, 재사용 시 정상 요금의 10% 수준으로만 과금하게 만듭니다. 제대로 사용하면 추론 비용(inference cost)을 50
90% 줄이고 첫 토큰 지연(first-token latency)을 4085% 줄일 수 있습니다.
유형: Build 언어: Python 선수 지식: Phase 11 · 01(Prompt Engineering), Phase 11 · 05(Context Engineering), Phase 11 · 11(Caching and Cost) 예상 시간: 약 60분
문제
코딩 에이전트(coding agent)는 대화(conversation)의 매 턴(turn)마다 같은 15,000 토큰짜리 시스템 프롬프트를 Claude에게 보냅니다. 입력 토큰(input tokens) 100만 개당 $3 기준으로 20턴을 진행하면 입력 비용만 $0.90입니다. 이는 사용자(user)의 실제 메시지(message) 비용을 포함하지 않은 금액입니다. 이를 하루 10,000 대화로 곱하면, 한 번도 바뀌지 않는 텍스트(text) 때문에 하루 $9,000짜리 청구서가 나오게 됩니다.
품질(quality)을 해치지 않고 프롬프트를 줄이는 것은 어렵고, 그렇다고 보내지 않을 수도 없습니다. 모델(model)은 매 턴마다 그 프롬프트가 필요합니다. 유일한 해법은 제공자가 이미 본 적이 있는 접두부에 대해 매번 전체 가격(full price)을 지불하지 않는 것입니다.
그 해법이 바로 프롬프트 캐싱입니다. Anthropic은 2024년 8월에 이 기능을 공개했고, 2025년에는 1시간짜리 확장 TTL 변형(1-hour extended-TTL variant)도 추가했습니다. OpenAI는 같은 해 후반에 자동(automatic) 방식의 캐싱을 도입했고, Google은 Gemini 1.5와 함께 명시적(explicit) 컨텍스트 캐싱을 제공했습니다. 이제 세 제공자 모두 자사 프런티어 모델(frontier model)에서 이를 일급(first-class) 기능으로 제공합니다.
개념
동작 원리. 어떤 요청의 접두부가 최근 요청의 접두부와 일치하면, 제공자는 토큰을 다시 인코딩(encoding)하지 않고 이전 실행(run)의 KV-cache를 그대로 제공합니다. 처음에는 작은 쓰기 프리미엄(write premium)을 지불하지만, 이후 모든 읽기(read)에서는 큰 폭의 할인을 받습니다.
2026년 기준 세 제공자의 방식.
| 제공자 | API 방식 | 히트 할인(hit discount) | 쓰기 프리미엄(write premium) | 기본 TTL | 캐시 가능 최소 크기 |
|---|---|---|---|---|---|
| Anthropic | content block에 명시적 cache_control 마커 부착 | 입력 토큰 90% 할인 | 25% 할증 | 5분(1시간까지 확장 가능) | 1,024 tokens(Sonnet/Opus), 2,048(Haiku) |
| OpenAI | 자동 접두부 탐지(automatic prefix detection) | 입력 토큰 50% 할인 | 없음 | 최대 1시간(best-effort) | 1,024 tokens |
| Google(Gemini) | 명시적 CachedContent API | 저장(storage) 단위로 과금, 읽기는 정상가의 약 25% | 토큰·시간(token·hour)당 저장 요금 | 사용자 지정(default 1시간) | 4,096 tokens(Flash), 32,768(Pro) |
불변 규칙. 세 제공자 모두 접두부만 캐싱합니다. 요청 사이에 토큰이 단 하나라도 달라지면, 처음으로 달라진 토큰 이후의 모든 부분은 미스(miss) 처리됩니다. 안정적인(stable) 부분은 위에 두고, 가변적인(variable) 부분은 아래에 두어야 합니다.
캐시 친화적 레이아웃(cache-friendly layout)
[system prompt] <-- 캐시 대상
[tool definitions] <-- 캐시 대상
[few-shot examples] <-- 캐시 대상
[retrieved documents] <-- 재사용되면 캐시, 아니면 캐시하지 않음
[conversation history] <-- 마지막 턴까지 캐시
[current user message] <-- 캐시하지 않음(매번 달라짐)
이 순서를 어기면 캐시가 히트(hit)하지 않습니다. 예를 들어 사용자 메시지를 시스템 프롬프트 위에 두거나, 동적 검색(dynamic retrieval) 결과를 few-shot 예시 사이에 끼워 넣으면 캐시는 계속 미스됩니다.
손익분기 계산(break-even calculation)
Anthropic의 25% 쓰기 프리미엄 때문에, 캐시된 블록은 최소 두 번 이상 읽혀야 순절감이 발생합니다. 1회 쓰기 + 1회 읽기는 요청당 평균 0.675배의 비용이 들고(약 32% 절감), 1회 쓰기 + 10회 읽기는 평균 0.205배까지 내려갑니다(약 80% 절감). 경험 법칙(rule of thumb)은 "TTL 안에서 최소 3회 이상 재사용될 것으로 예상되면 캐시한다"입니다.
직접 만들기
Step 1: 명시적 마커를 사용하는 Anthropic 프롬프트 캐싱
import anthropic
client = anthropic.Anthropic()
SYSTEM = [
{
"type": "text",
"text": "You are a senior Python reviewer. Follow the rubric exactly.\n\n" + RUBRIC_15K_TOKENS,
"cache_control": {"type": "ephemeral"},
}
]
def review(code: str):
return client.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
system=SYSTEM,
messages=[{"role": "user", "content": code}],
)
cache_control 마커는 Anthropic에게 해당 블록을 5분 동안 저장하라고 알려줍니다. 그 시간 안에 다시 사용하면 히트, 만료 후에 재사용하면 다시 쓰기가 발생합니다.
응답의 사용량(usage) 필드 예시:
response = review(code_a)
response.usage
# InputTokensUsage(
# input_tokens=120,
# cache_creation_input_tokens=15023, # 1.25배로 과금
# cache_read_input_tokens=0,
# output_tokens=340,
# )
response_b = review(code_b)
response_b.usage
# cache_creation_input_tokens=0
# cache_read_input_tokens=15023 # 0.1배로 과금
CI에서 두 필드를 모두 확인해야 합니다. 여러 요청을 보냈는데도 cache_read_input_tokens가 계속 0이라면, 캐시 키(cache key)가 흔들리고(drift) 있다는 신호입니다.
Step 2: 1시간 확장 TTL
장시간(long-running) 배치 작업(batch job)에서는 기본 5분 TTL이 작업 사이에 만료될 수 있습니다. 이때는 ttl을 직접 지정합니다.
{"type": "text", "text": RUBRIC, "cache_control": {"type": "ephemeral", "ttl": "1h"}}
1시간 TTL은 쓰기 프리미엄이 기존의 2배가 됩니다. 즉 기준 요금의 25%가 아니라 50%를 더 내게 됩니다. 하지만 접두부를 5회 이상 재사용하는 배치 작업에서는 빠르게 본전을 회수할 수 있습니다.
Step 3: OpenAI의 자동 캐싱
OpenAI에서는 직접 설정할 것이 없습니다. 1,024 토큰을 넘는 접두부가 최근 요청과 일치하면 자동으로 50% 할인이 적용됩니다.
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-5",
messages=[
{"role": "system", "content": SYSTEM_PROMPT}, # 길고 안정적인 부분
{"role": "user", "content": user_msg},
],
)
resp.usage.prompt_tokens_details.cached_tokens # 할인 적용된 토큰 수
캐시 친화적 레이아웃 규칙은 그대로 적용됩니다. 다만 Anthropic에서는 문제되지 않지만 OpenAI의 캐시를 깨뜨리는 요인이 두 가지 있습니다. 첫째는 캐시 키 구성 요소로 쓰이는 user 필드가 바뀌는 것이고, 둘째는 도구(tool)의 순서가 바뀌는 것입니다.
Step 4: Gemini의 명시적 컨텍스트 캐싱
Gemini는 캐시를 직접 생성하고 이름으로 참조하는 일급 객체(first-class object)로 다룹니다.
from google import genai
from google.genai import types
client = genai.Client()
cache = client.caches.create(
model="gemini-3-pro",
config=types.CreateCachedContentConfig(
display_name="rubric-v3",
system_instruction=RUBRIC,
contents=[FEW_SHOT_EXAMPLES],
ttl="3600s",
),
)
resp = client.models.generate_content(
model="gemini-3-pro",
contents=["Review this code:\n" + code],
config=types.GenerateContentConfig(cached_content=cache.name),
)
Gemini는 캐시가 살아 있는 동안 토큰·시간 단위로 저장 비용을 부과하고, 읽기는 정상 입력 요금의 약 25%로 과금합니다. 같은 거대한 프롬프트를 여러 세션(session)에 걸쳐, 여러 날 동안 재사용할 때 가장 잘 어울리는 형태입니다.
Step 5: 운영 환경에서 히트율 측정하기
code/main.py에는 세 제공자의 캐싱 방식을 시뮬레이션하면서 쓰기/읽기/미스 횟수를 추적하고, 1,000 요청당 혼합 비용(blended cost)을 계산하는 가상 회계 도구가 있습니다. 배포 게이트(deploy gate)에 목표 히트율을 설정하는 식으로 활용합니다. 대부분의 운영 환경 Anthropic 설정에서는, 예열(warmup) 이후 80%를 넘는 읽기 비중을 목표로 삼아야 합니다.
2026년에도 여전히 자주 배포되는 함정(pitfalls)
- 맨 위에 있는 동적 타임스탬프(dynamic timestamp). 시스템 프롬프트 맨 위에
"Current time: 2026-04-22 15:30:02"를 넣어두면 매 요청이 미스됩니다. 타임스탬프는 캐시 분기점(cache breakpoint) 아래로 옮겨야 합니다. - 도구 순서 변경(tool reordering). 도구는 안정적인 순서로 직렬화(serialize)해야 합니다. 배포 사이에 딕셔너리(dict) 순서가 흔들리면 모든 히트가 깨집니다.
- 자유 텍스트의 거의 중복(free-text near-duplicates). "You are helpful."과 "You are a helpful assistant."처럼 한 바이트(byte)만 달라도 전체가 미스가 됩니다.
- 너무 작은 블록(too-small blocks). Anthropic은 1,024 토큰의 하한(floor)을 강제합니다(Haiku는 2,048). 더 작은 블록은 알림 없이 조용히 캐시되지 않습니다.
- 눈 가린 비용 대시보드(blind cost dashboards). "input tokens"를 캐시된 것과 캐시되지 않은 것으로 나눠 보지 않으면, 트래픽(traffic) 감소를 캐시 효과로 착각하기 쉽습니다.
사용해보기
2026년의 캐싱 스택은 다음처럼 선택할 수 있습니다.
| 상황 | 선택 |
|---|---|
| 안정적인 10,000 토큰 이상의 시스템 프롬프트와 다수의 턴을 가진 에이전트 | Anthropic cache_control + 5분 TTL |
| 30분 이상 동일한 접두부를 재사용하는 배치 작업 | Anthropic ttl: "1h" |
| GPT-5 위에서 동작하는 서버리스(serverless) 엔드포인트, 별도 인프라 없음 | OpenAI 자동 캐싱(접두부를 안정적이고 길게 유지) |
| 거대한 코드/문서 말뭉치(corpus)를 여러 날 재사용 | Gemini 명시적 CachedContent |
| 여러 제공자 간 폴백(cross-provider fallback) | 캐시 가능한 접두부 레이아웃을 제공자마다 동일하게 유지해, 어느 쪽에서든 히트가 가능하게 한다 |
사용자 메시지 레이어에는 의미 기반 캐싱(semantic caching, Phase 11 · 11)을 함께 사용합니다. 프롬프트 캐싱은 토큰 단위로 동일한 재사용을, 의미 기반 캐싱은 의미가 동일한 재사용을 다룹니다.
산출물 만들기
outputs/skill-prompt-caching-planner.md를 다음 내용으로 저장합니다.
---
name: prompt-caching-planner
description: Design a cache-friendly prompt layout and pick the right provider caching mode.
version: 1.0.0
phase: 11
lesson: 15
tags: [llm-engineering, caching, cost]
---
Given a prompt (system + tools + few-shot + retrieval + history + user) and a usage profile (requests per hour, TTL needed, provider), output:
1. Layout. Reordered sections with a single cache breakpoint marked; explain which sections are stable, which are volatile.
2. Provider mode. Anthropic cache_control, OpenAI automatic, or Gemini CachedContent. Justify from TTL and reuse pattern.
3. Break-even. Expected reads per write within TTL; net cost vs no-cache with math.
4. Verification plan. CI assertion that cache_read_input_tokens > 0 on the second identical request; dashboard split by cached vs uncached tokens.
5. Failure modes. List the three most likely reasons the cache will miss in this setup (dynamic timestamp, tool reorder, near-duplicate text) and how you will prevent each.
Refuse to ship a cache plan that places a dynamic field above the breakpoint. Refuse to enable 1h TTL without a reuse count that makes the 2x write premium pay back.
기존 출력물 파일은 영어 prompt 본문을 그대로 두고, 학습자에게 한국어로 안내하도록 Guide the student in Korean. 한 줄만 추가합니다.
연습문제
- 쉬움. Claude에서 5,000 토큰짜리 시스템 프롬프트를 가진 10턴 대화를 실행해 봅니다.
cache_control없이 한 번,cache_control을 켜고 한 번 실행한 뒤, 각 경우의 입력 토큰 청구 금액을 비교해 보고합니다. - 중간. 프롬프트 템플릿(template)과 요청 로그(request log)를 입력받아, 제공자별 예상 히트율과 비용 절감액을 계산하는 테스트 도구(test harness)를 작성합니다. Anthropic 5분, Anthropic 1시간, OpenAI 자동, Gemini 명시적 캐시 네 가지를 비교합니다.
- 어려움. 레이아웃 최적화기(layout optimizer)를 만듭니다. 프롬프트와
stable=True/False로 표시된 필드 목록을 받아, 정보 손실 없이 캐시 친화성이 가장 높은 위치에 하나의 캐시 분기점을 두도록 프롬프트를 다시 구성합니다. 이를 실제 Anthropic 엔드포인트(endpoint)에서 검증합니다.
핵심 용어
| 용어 | 흔한 설명 | 실제 의미 |
|---|---|---|
| 프롬프트 캐싱(prompt caching) | "긴 프롬프트를 싸게 만드는 기능" | 일치하는 접두부에 대해 제공자 쪽의 KV-cache를 재사용하는 방식. 반복되는 입력 토큰에 50~90% 할인이 적용된다. |
cache_control | "Anthropic 마커" | "여기까지는 캐시 가능"임을 선언하는 content-block 속성. {"type": "ephemeral"} 형태로 쓴다. |
| 캐시 쓰기(cache write) | "프리미엄을 내는 단계" | 캐시를 채우는 첫 번째 요청. Anthropic에서는 입력 요금의 약 1.25배, OpenAI에서는 추가 비용이 없다. |
| 캐시 읽기(cache read) | "할인" | 접두부가 일치하는 후속 요청. Anthropic 10%, OpenAI 50%, Gemini 약 25%의 요금으로 과금된다. |
| TTL(Time To Live) | "얼마나 오래 살아 있는가" | 캐시가 따뜻하게 유지되는 시간. Anthropic은 기본 5분(1시간까지 확장 가능), OpenAI는 best-effort 최대 1시간, Gemini는 사용자가 직접 지정한다. |
| 확장 TTL(extended TTL) | "1시간짜리 Anthropic 캐시" | {"type": "ephemeral", "ttl": "1h"}. 쓰기 프리미엄은 2배지만 배치 재사용에서는 충분히 값어치를 한다. |
| 접두부 일치(prefix match) | "왜 내 캐시가 미스 났을까" | 시작부터 분기점까지 모든 토큰이 바이트 단위로 동일할 때만 캐시가 히트한다. |
| 컨텍스트 캐싱(context caching, Gemini) | "명시적인 그것" | 이름이 부여되고 저장 단위로 과금되는 Google의 캐시 객체. 거대한 말뭉치를 여러 날 재사용할 때 적합하다. |
더 읽을거리
- Anthropic — Prompt caching —
cache_control, 1시간 TTL, 손익분기 표를 다룹니다. - OpenAI — Prompt caching — 자동 접두부 매칭 방식을 설명합니다.
- Google — Context caching —
CachedContentAPI와 저장 요금 체계를 다룹니다. - Anthropic engineering — Prompt caching for long-context workloads — 지연 시간 수치가 포함된 최초 공개 글입니다.
- Phase 11 · 05(Context Engineering) — 캐시가 안착할 수 있도록 프롬프트를 어디서 잘라야 하는지 다룹니다.
- Phase 11 · 11(Caching and Cost) — 프롬프트 캐싱과 사용자 메시지 단의 의미 기반 캐싱을 함께 운용하는 방법을 다룹니다.
- Pope et al., "Efficiently Scaling Transformer Inference" (2022) — 프롬프트 캐싱이 사용자에게 노출하는 KV-cache 메모리 모델을 설명합니다. 캐시된 접두부를 다시 읽는 것이 다시 계산하는 것보다 왜 약 10배 저렴한지 이해할 수 있습니다.
- Agrawal et al., "SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills" (2023) — 프롬프트 캐싱이 단축하는 프리필(prefill) 단계를 설명합니다. 캐시 히트 시 첫 토큰까지의 시간(TTFT)이 크게 줄고, 토큰 간 시간(TPOT)은 거의 영향을 받지 않는 이유를 이해할 수 있습니다.
- Leviathan et al., "Fast Inference from Transformers via Speculative Decoding" (2023) — 프롬프트 캐싱은 추측 디코딩(speculative decoding), Flash Attention, MQA/GQA와 함께 추론 비용 곡선을 바꾸는 지렛대(lever) 중 하나입니다. 나머지 세 가지와 함께 읽으면 좋은 글입니다.