프롬프트 캐싱(Prompt Caching)과 시맨틱 캐싱(Semantic Caching)의 경제성
가격 기준 시점은 2026년 4월입니다. 아래 등장하는 모든 수치는 이 lesson을 발행한 시점에 수집한 공급사(vendor) 요금표를 반영합니다. 이후 다른 문서나 운영 자료에서 인용하기 전에는 반드시 본문에 연결된 공식 문서를 다시 확인하시기 바랍니다.
캐싱(caching)은 두 개의 계층에서 일어납니다. L2 계층은 공급사(provider) 수준의 프롬프트 또는 프리픽스 캐싱(prompt/prefix caching)으로, 반복되는 프리픽스(prefix)에 대해 어텐션 키-값(Attention Key-Value; KV)을 재사용하는 방식입니다. Anthropic의 프롬프트 캐싱 문서는 긴 프롬프트에서 최대 90% 비용 절감과 85% 지연시간(latency) 감소를 광고합니다. Claude 3.5 Sonnet 모델 기준으로 캐시 읽기(cache read) 단가는 신규 입력(fresh input)의 100만 토큰당 3.00달러 대비 0.30달러이며, 기본 5분짜리 유효시간(Time To Live; TTL)을 제공하고, 1시간짜리 TTL 옵션을 선택하면 쓰기 비용이 두 배로 붙습니다(docs.anthropic.com, 2026-04). OpenAI의 프롬프트 캐싱은 1024 토큰 이상의 프롬프트에 자동으로 적용되며, 캐시된 입력(cached input)은 신규 입력 대비 대략 90% 할인된 가격으로 책정됩니다(platform.openai.com, 2026-04). 모델별로 정확한 캐시 단가는 실시간 요금표에 따라 달라집니다. L1 계층은 애플리케이션 수준(app-level)의 시맨틱 캐싱(semantic caching)으로, 임베딩 유사도(embedding similarity)가 일정 기준을 넘으면 LLM 호출 자체를 건너뜁니다. 공급사가 흔히 말하는 "정확도 95%"라는 표현은 캐시에서 반환된 응답이 적절했는지를 나타내는 일치 정확도이지, 적중률(hit rate)을 뜻하지 않습니다. 실제 운영(production) 환경에서 보고된 적중률은 개방형 채팅(open-ended chat)의 약 10%부터 정형화된 자주 묻는 질문(structured FAQ)의 약 70%까지 폭넓게 분포합니다. 어느 공급사도 공식 기준값(baseline)을 공개하지 않으므로, 이런 수치는 보장된 성능이 아니라 커뮤니티에서 보고된 운영 측정값으로 봐야 합니다. 운영 현장에서 자주 겪는 함정은 두 가지입니다. 첫째, 병렬화(parallelization)는 캐싱 효과를 무력화합니다. 첫 번째 캐시 쓰기가 끝나기 전에 N개의 병렬 요청을 한꺼번에 보내면 비용이 몇 배로 부풀어 오릅니다. 둘째, 동적인 콘텐츠(dynamic content)를 프리픽스 안에 섞어 두면 캐시 적중이 거의 0으로 무너집니다. ProjectDiscovery는 동적인 텍스트를 캐시 대상 프리픽스 밖으로 옮기는 것만으로 적중률을 7%에서 74%로 끌어올렸다고 보고했습니다(2025-11).
유형: Learn
언어: Python (표준 라이브러리만 사용한 두 계층 캐시 시뮬레이터)
선수 지식: Phase 17 · 04 (vLLM Serving Internals), Phase 17 · 06 (SGLang RadixAttention)
예상 시간: 약 60분
학습 목표
- 공급사가 어텐션 KV를 재사용하는 L2 프롬프트/프리픽스 캐싱과, 비슷한 프롬프트에서 LLM 호출을 우회하는 L1 시맨틱 캐싱을 구분합니다.
- Anthropic의 명시적
cache_control 표기와 두 가지 TTL 옵션(5분과 1시간), 그리고 각각에 붙는 가격 배수를 설명합니다.
- 적중률, 프롬프트와 응답의 토큰 비율, 토큰 단가를 바탕으로 월간 예상 절감액을 계산합니다.
- 청구액을 5~10배까지 부풀리는 병렬화 안티패턴(parallelization anti-pattern)과, 적중률을 무너뜨리는 동적 콘텐츠 안티패턴(dynamic content anti-pattern)의 이름과 구조를 설명합니다.
문제
검색 증강 생성(Retrieval-Augmented Generation; RAG) 서비스에 프롬프트 캐싱을 추가했습니다. 그런데 청구서는 그대로입니다. 적중률을 측정해 보니 7%입니다. 프롬프트는 정적인 것처럼 보이지만 실제로는 그렇지 않습니다. 시스템 프롬프트 안에 분 단위까지 포맷된 현재 시각, 요청 식별자(request ID), 그리고 다양성을 위해 무작위로 순서를 바꾼 예시들이 들어 있기 때문입니다. 모든 요청은 새로운 캐시 항목을 쓰기만 하고, 읽기는 한 번도 일어나지 않습니다.
별개의 문제도 있습니다. 우리 에이전트(agent)는 사용자 질문 하나마다 10개의 도구 호출(tool call)을 병렬로 실행합니다. 그런데 10개 요청 모두가 첫 번째 캐시 쓰기가 끝나기 전에 공급사 측에 도착합니다. 결과는 10번의 쓰기와 0번의 읽기입니다. "캐싱을 켰다"고 기대했던 비용보다 청구서가 5~10배 커지게 됩니다.
캐싱은 단순한 옵션 플래그(flag)가 아니라 하나의 프로토콜(protocol)입니다. 두 개의 계층이 있고, 각 계층마다 서로 다른 실패 모드(failure mode)가 존재합니다.
개념
L2 — 공급사 측 프롬프트/프리픽스 캐싱
공급사는 캐시 가능한 프리픽스에 대해 어텐션 KV를 저장해 두고, 다음 요청에서 같은 프리픽스가 들어오면 이를 재사용합니다. 쓰기 비용은 한 번만 지불하고, 이후의 읽기는 거의 공짜에 가까운 가격으로 처리됩니다.
Anthropic(Claude 3.5 / 3.7 / 4 시리즈): 요청 안에서 명시적인 cache_control 마커를 사용합니다. 어떤 블록을 캐시 대상으로 볼지 사용자가 태그로 표시합니다. TTL은 5분(쓰기 비용 1.25배) 또는 1시간(쓰기 비용 2배) 중에서 선택할 수 있습니다. Claude 3.5 Sonnet 기준 캐시 읽기 단가는 100만 토큰당 0.30달러, 신규 입력은 100만 토큰당 3.00달러이므로 약 10배 저렴합니다(docs.anthropic.com, 2026-04 기준). 모델마다 단가가 다르며(Opus, Haiku는 별도로 공개됨), 실제 사용 전에는 항상 최신 가격 페이지를 다시 확인해야 합니다.
OpenAI: 1024 토큰 이상의 프롬프트에는 자동 캐싱(automatic caching)이 적용됩니다(platform.openai.com, 2026-04). 명시적인 플래그는 따로 없습니다. 현재 공개된 gpt-4o, gpt-5 요금표에서 캐시된 입력은 신규 입력보다 대략 10배 저렴합니다. 공식 문서나 릴리스 노트에는 공식적인 적중률 기준값이 공개되어 있지 않습니다. 커뮤니티 보고를 종합하면, 프롬프트를 세심하게 설계했을 때 대략 30~60% 사이에 분포합니다. 실제 서비스에서는 usage.cached_tokens 값을 모니터링해 자신만의 수치를 직접 측정해야 합니다.
Google(Gemini): 명시적인 API를 통해 컨텍스트 캐싱(context caching)을 제공합니다. 100만 토큰 규모의 컨텍스트를 다룬다면 캐싱의 경제적 효과는 더욱 커집니다.
자체 호스팅(self-hosted, vLLM, SGLang): Phase 17 · 06에서 RadixAttention을 다룹니다. 같은 패턴을 자신의 컴퓨팅(compute) 자원 위에서 직접 운영하는 형태입니다.
L1 — 애플리케이션 수준의 시맨틱 캐싱
LLM을 호출하기 전에 먼저 프롬프트를 해시(hash)하고, 임베딩(embedding)을 만들고, 비슷한 캐시 항목이 있는지를 찾습니다. 보통 코사인 유사도(cosine similarity)가 임계값(threshold) 이상, 예를 들어 0.95 이상이면 적중으로 봅니다. 적중이면 캐시에 저장된 응답을 그대로 반환하고, 미스(miss)면 LLM을 호출한 뒤 그 결과를 캐시에 저장합니다.
오픈소스(open-source) 도구로는 Redis Vector Similarity, GPTCache, Qdrant 등이 있습니다. 상용 제품으로는 Portkey Cache, Helicone Cache가 있습니다.
공급사가 말하는 정확도 수치는 캐시가 반환한 응답이 의미적으로 적절했던 비율을 뜻하는 것이지, 얼마나 자주 적중이 발생하는지를 뜻하지 않습니다. 실제 운영 환경에서의 적중률은 작업 유형에 따라 다음처럼 크게 달라집니다.
- 개방형 채팅(open-ended chat): 10~15%.
- 정형화된 자주 묻는 질문(structured FAQ) / 고객 지원: 40~70%.
- 코드 관련 질문(code questions): 20~30%. 작은 변형만 있어도 적중이 깨집니다.
- 같은 프롬프트가 반복되는 음성 에이전트(voice agent): 50~80%. 음성 정규화(voice normalization)와 고정된 응답 집합이 적중률을 끌어올립니다.
병렬화 안티패턴(parallelization anti-pattern)
에이전트가 10개의 도구 호출을 병렬로 만든다고 가정해 봅시다. 모든 요청이 동일한 4K 토큰 규모의 시스템 프롬프트를 공유합니다. Anthropic의 캐시 쓰기는 요청 단위로 이루어집니다. 첫 번째 캐시 쓰기는 공급사가 프롬프트를 본 시점부터 약 300ms 뒤에 완료됩니다. 그런데 두 번째부터 열 번째 요청은 같은 밀리초 구간 안에 함께 도착하기 때문에 모두 캐시 미스를 봅니다. 결과적으로 10번의 쓰기 비용은 더 비싼 단가로 지불하면서, 읽기 할인은 한 번도 받지 못합니다.
해결책은 "첫 요청 직렬화, 나머지 병렬화(sequential-first batching)" 패턴입니다. 1번 요청을 먼저 단독으로 보내고, 그 요청이 캐시를 채운 다음에야 2번부터 10번까지를 한꺼번에 발사합니다. 첫 번째 도구 호출에 약 300ms가 더 추가되지만, 청구서는 5~10배 줄어듭니다.
동적 콘텐츠 안티패턴(dynamic content anti-pattern)
시스템 프롬프트가 다음처럼 생겼다고 가정합니다.
You are a helpful assistant. The current time is 14:32:17.
User ID: abc123. Today is Tuesday...
모든 요청이 서로 다른 내용이 되어 버립니다. 모든 요청은 쓰기를 일으키고, 적중은 0이 됩니다.
해결책은 진짜로 정적인 내용만 캐시 가능한 프리픽스 안에 두고, 동적인 내용은 캐시 경계(cache boundary) 바깥에 붙이는 것입니다.
[cacheable]
You are a helpful assistant. [rules, examples, instructions]
[/cacheable]
[dynamic, not cached]
Current time: 14:32:17. User: abc123.
ProjectDiscovery는 바로 이 방식으로 캐시 적중률을 7%에서 74%로 끌어올렸고, 그 구조(anatomy)를 블로그에 공개했습니다.
야간 배치 작업에는 배치(batch)와 캐시를 함께 쌓기
배치 API(Phase 17 · 15에서 다룸)는 24시간 처리(turnaround)를 허용하는 조건에서 50% 할인을 제공합니다. 그 위에 캐시된 입력까지 쌓으면 대략 10배의 추가 절감 효과를 얻을 수 있습니다. 야간에 수행하는 분류(classification), 라벨링(labeling), 리포트 생성 같은 작업은 배치와 캐시를 함께 사용하면 동기식(synchronous) 비캐시 비용의 약 10% 수준까지 떨어질 수 있습니다.
기억해야 할 숫자들
아래의 가격 데이터는 본문에 연결된 공급사 공식 문서에서 2026년 4월에 수집한 값이며, 몇 달마다 바뀔 수 있습니다. 실제 의사결정에 사용하기 전에 반드시 다시 확인하시기 바랍니다.
- Anthropic 캐시 읽기: Claude 3.5 Sonnet 기준 100만 토큰당 0.30달러로, 신규 입력보다 약 10배 저렴합니다(docs.anthropic.com).
- Anthropic 캐시 쓰기 가산금(write premium): 5분 TTL은 1.25배, 1시간 TTL은 2배입니다.
- OpenAI 자동 캐싱: 1024 토큰 이상의 프롬프트에 적용됩니다. 현재 요금표 기준으로 캐시된 입력은 신규 입력의 약 10% 가격입니다(platform.openai.com).
- 시맨틱 캐시 적중률(커뮤니티 보고 기준): 개방형 채팅 약 10%, 정형화된 FAQ에서는 최대 약 70%. 공급사 공식 기준값이 아닙니다.
- ProjectDiscovery: 동적 콘텐츠를 프리픽스 밖으로 옮겨 적중률을 7%에서 74%로 끌어올렸습니다(project blog, 2025-11).
- 병렬화 안티패턴: N개의 병렬 요청이 첫 캐시 쓰기를 놓치면 청구서가 통상 5~10배 부풀어 오른다는 보고가 있습니다.
사용해보기
code/main.py는 혼합 작업 부하(mixed workload)에서 L1과 L2 캐싱을 함께 시뮬레이션합니다. 적중률, 청구액, 병렬화로 인한 페널티(penalty)를 함께 보고합니다.
산출물 만들기
이 lesson은 outputs/skill-cache-auditor.md를 산출물로 만듭니다. 프롬프트 템플릿과 트래픽 정보가 주어지면 캐시 가능성을 감사(audit)하고, 프롬프트 구조 재구성(restructure)을 추천하는 스킬입니다.
연습문제
- 쉬움:
code/main.py를 실행합니다. 병렬화 플래그를 켜고 끌 때 청구액이 얼마나 달라지는지 확인합니다.
- 쉬움: 시스템 프롬프트 안에 날짜가 들어 있다고 가정합니다. 이 날짜를 캐시 경계 밖으로 옮긴 뒤, 이전과 이후의 적중률을 산수로 비교해 보입니다.
- 중간: 자신의 요청 도착률(arrival rate)이 주어졌다고 할 때, 1시간 TTL(쓰기 비용 2배)과 5분 TTL(쓰기 비용 1.25배) 사이의 손익 분기점(break-even point)을 계산합니다.
- 중간: 시맨틱 캐시 임계값(threshold)이 0.95일 때 적중률은 20%이지만, 0.85일 때는 50% 적중하면서 잘못된 캐시 응답이 함께 보입니다. 올바른 임계값을 고르고 그 근거를 설명합니다.
- 어려움: 사용자 질문마다 10개의 병렬 하위 질의(sub-query)를 배치로 처리한다고 가정합니다. 종단 간 지연시간(end-to-end latency)을 늘리지 않으면서 캐시 친화적으로 동작하도록 다시 설계합니다.
핵심 용어
| 용어 | 흔한 설명 | 실제 의미 |
|---|
| L2 prompt cache | "prefix cache" | 공급사가 반복되는 프리픽스의 KV를 저장하는 구조 |
cache_control | "Anthropic cache marker" | 캐시 가능한 블록을 표시하는 명시적 속성(attribute) |
| Cache write premium | "write tax" | 첫 미스에서 캐시로 전환되는 단계에 붙는 추가 비용(1.25배 또는 2배) |
| L1 semantic cache | "embedding cache" | LLM 호출 전 애플리케이션 단에서 해시와 임베딩으로 적중을 찾는 캐시 |
| GPTCache | "LLM caching lib" | 널리 쓰이는 오픈소스 L1 캐시 라이브러리 |
| Cache hit rate | "hits / total" | 전체 요청 중 캐시에서 처리된 비율 |
| Parallelization anti-pattern | "the N-write trap" | N개의 병렬 요청이 캐시를 N번 놓치는 함정 |
| Dynamic content trap | "the time-in-prompt trap" | 프리픽스 안의 동적인 바이트 때문에 적중률이 무너지는 문제 |
| RadixAttention | "intra-replica cache" | SGLang의 프리픽스 캐시 구현 |
더 읽을거리