본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 01. 18:16

Claude를 활용한 프롬프트 캐싱 (Prompt Caching): 프로덕션 환경에서 AI API 비용을 90% 절감하는 방법 (2026

요약

Anthropic의 Claude 프롬프트 캐싱을 활용하여 API 비용을 최대 90% 절감하고 지연 시간을 85% 낮추는 방법을 설명합니다. 에이전트 및 RAG 시스템에서 발생하는 반복적인 입력 토큰 비용 문제를 해결하기 위한 프로덕션 패턴과 캐시 메커니즘을 다룹니다.

핵심 포인트

  • 캐시 읽기 시 입력 토큰 비용 90% 할인
  • 긴 컨텍스트 호출 시 지연 시간 최대 85% 감소
  • 캐시 쓰기 시 1.25배의 일회성 프리미엄 발생
  • 프롬프트 내 최대 4개의 캐시 중단점 설정 가능
  • 접두사 트리 구조를 통한 바이트 단위 일치 확인

요약 (TL;DR) — Anthropic의 프롬프트 캐싱 (Prompt Caching)을 사용하면 캐시된 입력 토큰 (input tokens)에 대해 90%의 할인을 받을 수 있으며, 긴 컨텍스트 (long-context) 호출 시 지연 시간 (latency)을 최대 85%까지 낮출 수 있습니다. 하지만 이러한 이점은 캐시 중단점 (cache breakpoints), TTL (Time To Live), 그리고 실제로 무엇이 캐시를 무효화 (invalidate)하는지를 이해할 때만 나타납니다. 이 가이드에서는 우리가 사용하는 5가지 프로덕션 패턴, 실제 벤치마크 (benchmarks), 그리고 히트율 (hit rate)을 조용히 떨어뜨리는 함정들을 살펴봅니다.

아무도 경고해주지 않는 비용 문제

Claude를 사용하여 에이전트 (agent), RAG 시스템, 코드 어시스턴트 (code assistant), 고객 지원 봇 (customer support bot) 등 본격적인 서비스를 출시할 때, 여러분은 동일하고 불편한 진실을 발견하게 됩니다: 입력 토큰 (input token) 비용이 출력 토큰 (output token) 비용을 압도한다는 사실입니다.

전형적인 에이전트 루프 (agent loop)는 다음과 같습니다:

  • 시스템 프롬프트 (System prompt): ~3,000 토큰 (지침, 페르소나, 제약 사항)
  • 도구 정의 (Tool definitions): 4,000 토큰 (1020개 도구에 대한 JSON 스키마)
  • 대화 기록 (Conversation history): 5,000~50,000 토큰 (매 턴마다 증가)
  • RAG 컨텍스트 (RAG context): 쿼리당 5,000~20,000 토큰
  • 사용자 메시지 (User message): ~200 토큰
  • 모델 출력 (Model output): ~500 토큰

매 턴마다 여러분은 동일한 시스템 프롬프트, 동일한 도구 정의, 그리고 대화 기록의 대부분을 다시 전송합니다. 입력 토큰 100만 개당 3달러인 Claude Sonnet 4.6을 기준으로, 20번의 대화 턴에 걸쳐 15,000 토큰의 접두사 (prefix)를 전송하면 유용한 출력 토큰을 단 하나도 생성하기 전에 입력 비용만으로 대화당 $0.90가 소요됩니다.

이를 일일 활성 사용자(DAU) 10,000명으로 곱하면, 이미 보낸 콘텐츠를 다시 토큰화 (re-tokenize)하는 데만 하루에 $9,000를 낭비하게 됩니다.

이것이 바로 프롬프트 캐싱 (prompt caching)이 해결하고자 하는 문제입니다.

Claude의 프롬프트 캐싱이 실제로 하는 일

Anthropic의 프롬프트 캐싱은 API가 프롬프트 접두사 (prefix)의 내부 상태 (internal state)를 저장하고 이후의 요청에서 이를 재사용할 수 있게 해줍니다. 두 가지 수치가 중요합니다:

작업기본 입력 대비 가격
캐시 쓰기 (Cache write) (접두사가 처음 나타날 때)기본 입력 비용의 1.25배
캐시 읽기 (Cache read) (이후 히트 시)기본 입력 비용의 0.10배 (90% 할인)

캐시를 작성할 때 소정의 일회성 프리미엄(premium)을 지불하면, 그 이후의 모든 히트(hit)는 정상 가격의 10%만 지불하면 됩니다. 손익분기점은 두 번째 요청 이후입니다. 즉, 한 번의 읽기(read)를 초과하는 시점부터 비용을 절감하게 됩니다.

멘탈 모델 (The mental model)

이를 체크포인트가 있는 **접두사 트리 (prefix tree)**라고 생각하세요. 프롬프트 내의 최대 4개 지점에 cache_control을 사용하여 표시할 수 있으며, Claude는 프롬프트의 시작부터 각 중단점(breakpoint)까지의 모든 내용을 캐싱합니다. 다음 요청 시, 접두사(prefix)가 **바이트 단위로 일치 (byte-for-byte)**하면 캐시 히트(cache hit)가 발생합니다.

Claude가 프롬프트를 처리하는 순서는 고정되어 있습니다:

tools → system → messages (oldest → newest)

캐시 중단점은 반드시 이 순서를 준수해야 합니다. 이전의 모든 내용을 캐싱하지 않고는 나중에 나오는 블록만 따로 캐싱할 수 없습니다.

TTL 함정 (The TTL trap)

기본 캐시 TTL(Time To Live)은 5분이며, 읽을 때마다 갱신됩니다. 프리미엄 옵션으로 1시간 TTL을 사용할 수 있습니다 (작성 시 비용은 더 높지만, 읽기 시 비용은 동일함). 대부분의 팀은 5분이면 충분한 상황에서도 1시간 캐시를 사용하며 과도한 비용을 지불합니다. 트래픽이 일정하다면, 모든 요청이 TTL을 갱신하므로 캐시는 사실상 영구적으로 유지됩니다.

프로덕션 환경에서의 Claude API 메커니즘에 대해 더 깊이 알고 싶으신가요? 프롬프트 캐싱 (Prompt caching), 도구 사용 (tool use), 배치 API (batch API), 스트리밍 (streaming), 그리고 비용 최적화 (cost optimization)에 대해 Cursuri-AI.ro의 Advanced LLM Integration 코스에서 심도 있게 다룹니다.

패턴 1: 시스템 프롬프트와 도구 정의 캐싱하기

이것은 가장 높은 ROI(투자 대비 효율)를 낼 수 있는 변경 사항이며, 대부분의 코드베이스가 첫 시도에서 이를 잘못 구현합니다.

잘못된 예 (캐싱 없음):

import anthropic

client = anthropic.Anthropic()
...

올바른 예 (캐싱 적용):

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
...

주의 깊게 봐야 할 두 가지 사항이 있습니다:

주의 깊게 봐야 할 두 가지 사항이 있습니다:

  1. **시스템 블록(system block)의 cache_control**은 시스템 프롬프트(system prompt)까지의 모든 내용을 캐싱합니다.
  2. **마지막 도구(last tool)의 cache_control**은 도구 정의(tool definitions)까지의 모든 내용을 캐싱합니다. 이는 위에서 언급한 처리 순서에 따라 도구가 시스템보다 먼저 평가되기 때문에 매우 중요합니다.

잠시만요 — 방금 설명한 내용은 사실 틀렸습니다. 정정하겠습니다: 처리 순서가 tools → system → messages이기 때문에, 마지막 도구cache_control을 설정하면 도구들만 캐싱되고, 시스템에 설정하면 도구와 시스템 모두를 캐싱합니다. 일반적으로는 시스템 중단점(breakpoint)만 있으면 충분합니다. 시스템 설정이 그 이전의 모든 내용을 포함하기 때문입니다.

응답 읽기

API는 response.usage를 통해 캐시 통계(cache stats)를 반환합니다:

print(response.usage.cache_creation_input_tokens)  # 캐시에 기록된 토큰 (비용 1.25배)
print(response.usage.cache_read_input_tokens)      # 캐시에서 읽은 토큰 (비용 0.10배)
print(response.usage.input_tokens)                 # 캐싱되지 않은 토큰 (비용 1배)

첫 번째 요청 시에는 cache_creation_input_tokens가 높고, cache_read_input_tokens는 0입니다.
5분 이내의 모든 후속 요청 시에는 cache_creation_input_tokens는 0이고, cache_read_input_tokens가 높게 나타납니다. 이것이 바로 비용 절감의 핵심 조건(win condition)입니다.

패턴 2: 순환 중단점(rolling breakpoints)을 활용한 대화 기록 캐싱

멀티 턴 에이전트(multi-turn agent)에서는 턴이 진행될 때마다 대화 내용이 늘어납니다. 만약 시스템 프롬프트만 캐싱한다면, 이전의 모든 턴을 매번 전체 비용을 지불하며 다시 전송하게 됩니다.

비결은 가장 최근의 어시스턴트 메시지(assistant message)에 두 번째 캐시 중단점을 추가하여, 해당 시점까지의 전체 대화 내용을 캐싱하는 것입니다:

def build_messages_with_cache(history, new_user_message):
    """
    history: list of {"role": "user"|"assistant", "content": ...}
...```

이제 매 새로운 턴은 이전의 전체 대화 내용을 캐시에서 읽어옵니다. 턴당 비용은 대화 길이에 따라 선형적으로 증가하는 대신 거의 일정하게 유지됩니다.

### 4개 중단점 예산

Claude는 요청당 최대 **4개의 캐시 중단점**을 허용합니다. 일반적인 프로덕션 레이아웃에서는 이 4개를 모두 사용합니다:

1. **Breakpoint 1**: 도구 (tools)의 끝
2. **Breakpoint 2**: 시스템 프롬프트 (system prompt)의 끝
3. **Breakpoint 3**: "안정적인 (stable)" 대화 기록의 끝 (턴 1부터 N-2까지)
4. **Breakpoint 4**: "최근 (recent)" 기록의 끝 (턴 N-1)

이를 통해 계층화된 캐시 (layered cache)를 구성할 수 있습니다: 도구는 거의 변하지 않고, 시스템도 거의 변하지 않으며, 오래된 기록은 절대 변하지 않고, 최근 기록은 슬라이딩(sliding)됩니다. 각 계층은 독립적으로 캐시 히트 (hit) 또는 미스 (miss)가 발생합니다.

## 패턴 3: 사용자 쿼리와 별도로 퓨샷 예시 (few-shot examples) 캐싱하기

퓨샷 프롬프팅 (Few-shot prompting)은 프로덕션 LLM 애플리케이션에서 가장 영향력이 큰 기술 중 하나이며, 캐싱을 하지 않을 경우 가장 비용이 많이 드는 기술 중 하나이기도 합니다. 5~10개의 예시를 포함하는 전형적인 퓨샷 블록은 8,000~15,000 토큰을 소모할 수 있습니다.

FEW_SHOT_EXAMPLES = """
Example 1:
Input: ...
...


핵심 규칙: **변하는 콘텐츠를 마지막에 배치하세요**. 캐시는 접두사 일치 (prefix matches) 방식에서만 작동합니다. 만약 사용자별 데이터가 프롬프트 중간에 위치한다면, 그 뒤에 오는 모든 내용은 캐싱할 수 없게 됩니다.

## 패턴 4: 캐싱된 문서 청크 (document chunks)를 활용한 RAG

RAG 시스템은 검색된 컨텍스트 (retrieved context)가 크고 쿼리마다 고유하기 때문에 토큰 비용을 폭증시키는 것으로 악명이 높습니다. 검색된 청크 자체를 캐싱할 수는 없지만 (청크는 계속 변하므로), 이를 둘러싼 프레임워크는 캐싱할 수 있습니다:

def rag_query(user_question, retrieved_chunks):
return client.messages.create(
model="claude-sonnet-4-6",
...


안정적인 지식 베이스 (기업 문서, 제품 매뉴얼, 코드베이스)를 사용하는 RAG의 경우, 더 발전된 패턴이 있습니다: **문서를 고정된 크기의 캐싱 가능한 블록으로 미리 타일링 (pre-tile)하고**, 검색 전략을 선택할 때 조각(slices)보다는 블록 전체를 반환하는 데 유리하도록 설정하는 것입니다. 이를 통해 자주 사용되는 문서 (hot documents)에 대한 막대한 비용 절감을 위해 검색 정밀도를 일부 희생할 수 있습니다.

> 프로덕션용 RAG 시스템을 구축한다면, [Cursuri-AI.ro의 RAG (Retrieval-Augmented Generation) 코스](https://cursuri-ai.ro/courses/rag-retrieval-augmented-generation)에서 캐싱 전략, 검색 최적화, 하이브리드 검색, 그리고 평가 파이프라인 (eval pipelines)을 엔드 투 엔드 (end-to-end)로 다룹니다.

## 패턴 5: 장기 실행 에이전트 (long-running agents)에서 도구 결과 캐싱하기

에이전트 루프 (Agent loops)는 캐싱의 최적 지점입니다. 에이전트는 `tool_call → tool_result → tool_call → tool_result` 사이클을 실행하며, 각 반복(iteration)마다 새로운 도구 결과 (tool result)로 인해 프롬프트가 커집니다. 캐싱이 없다면, 매 반복마다 전체 이력을 다시 비용 청구하게 됩니다.

def agent_loop(initial_user_message, tools):
messages = [{"role": "user", "content": initial_user_message}]

...


4,000 토큰의 시스템 프롬프트 (system prompt)와 8,000 토큰의 도구 (tools)를 사용하는 15단계 에이전트 실행의 경우, 이 패턴은 캐싱을 사용하지 않았을 때보다 입력 비용을 **약 80~88%** 절감합니다.

> 에이전트 루프, 도구 설계, 다단계 계획 (multi-step planning) 및 비용 모델링 (cost modeling)은 [Cursuri-AI.ro의 AI Agents & Automation 코스](https://cursuri-ai.ro/courses/ai-agents-automatizare)의 핵심 주제이며, 이 코스는 여기에 제시된 것과 동일한 Claude Agent SDK 패턴을 기반으로 구축되었습니다.

## 실제 벤치마크: 전 vs 후

이 수치는 Claude Sonnet 4.6에서 실행되는 프로덕션 코드 리뷰 에이전트의 데이터로, 각 12턴(turn)으로 구성된 1,000개의 대화를 평균한 결과입니다.

| 지표 | 캐싱 미사용 (Uncached) | 캐싱 사용 (Cached) | 변화량 |
| --- | --- | --- | --- |
| 턴당 평균 입력 토큰 | 18,400 | 18,400 | — |
| ... |

지연 시간 (latency) 측면의 이점은 비용 절감만큼이나 놀라웠습니다. 캐시 읽기 (Cache reads)는 프롬프트 처리 (prompt processing) 단계를 완전히 건너뛰는데, 이 단계는 긴 컨텍스트 (long contexts)에서 첫 번째 토큰 생성 시간 (time-to-first-token)의 대부분을 차지하기 때문입니다.

## 히트율 (hit rate)을 조용히 떨어뜨리는 함정들

다음은 저희가 직접 저질렀거나 프로덕션 코드 리뷰 과정에서 목격한 실수들입니다.

### 1. 공백 및 포맷팅 드리프트 (Whitespace and formatting drift)

캐시 히트 (Cache hits)가 발생하려면 **바이트 단위로 정확히 일치하는 접두사 (byte-exact prefix matches)**가 필요합니다. 만약 시스템 프롬프트를 f-string으로 생성하면서 타임스탬프, 조건부 줄바꿈, 또는 마지막 공백을 추가한다면 캐시가 무효화됩니다.

매 분마다 캐시를 깨뜨림 (BREAKS the cache)

system = f"You are a helpful assistant. Current time: {datetime.now()}"

...


프롬프트에 숨겨진 가변성이 있는지 감사하십시오: 로케일 (locale) 형식이 적용된 숫자, 이전 버전 Python에서의 딕셔너리 (dict) 반복 순서, 배포 시 필드 순서가 바뀌는 도구 정의 (tool definitions) 등이 해당됩니다.

### 2. 도구 정의의 순서 변경 (Reordering tool definitions)

만약 딕셔너리 (dict)로부터 도구 스키마 (tool schemas)를 생성하는데, 실행할 때마다 딕셔너리 반복 (iteration) 순서가 바뀐다면 캐시가 증발해 버립니다. 전송하기 전에 **항상 도구 정의를 정렬 (sort)** 하세요:

tools = sorted(generate_tools(), key=lambda t: t["name"])


### 3. 잘못된 중단점 배치 (Wrong breakpoint placement)

중단점 (Breakpoints)은 캐싱하려는 콘텐츠의 **뒤**에 와야 하며, 앞이 아닙니다. 중단점은 "여기까지의 모든 것을 캐싱하라"는 표시입니다. 시스템 프롬프트 (system prompt) 대신 사용자 메시지 (user message)에 중단점을 두는 것은 흔한 초보적인 실수입니다.

### 4. 너무 작은 접두사 캐싱 (Caching tiny prefixes)

캐싱 가능한 최소 크기가 존재합니다:

- **Claude Sonnet & Opus**: 1,024 토큰 (tokens)
- **Claude Haiku**: 2,048 토큰 (tokens)

최소 크기 미만일 경우, `cache_control`은 조용히 무시됩니다. API가 에러를 발생시키지는 않지만, 캐싱이 수행되지 않을 뿐입니다. 캐시가 실제로 작성되었는지 확인하려면 첫 번째 요청에서 항상 `response.usage.cache_creation_input_tokens > 0` 인지 확인하세요.

### 5. 간헐적 트래픽에서의 5분 TTL 무시 (Ignoring the 5-minute TTL on bursty traffic)

트래픽이 간헐적(bursty)이라면 — 즉, 업무 시간에는 많고 밤에는 거의 없다면 — 5분 캐시는 세션 사이에 만료될 것이며, 매번 쓰기 프리미엄 (write premium) 비용을 지불하게 됩니다. 간헐적인 패턴의 경우 다음 중 하나를 선택하세요:

- 1시간 TTL 사용 (쓰기 비용은 더 비싸지만, 읽기 가격은 동일)
- 또는 예상되는 유휴 시간 (idle windows) 동안 4분마다 작은 "keep-alive" 요청을 전송

### 6. 캐싱된 모델과 캐싱되지 않은 모델의 혼용 (Mixing cached and uncached models)

캐시는 **모델별 (model-specific)** 입니다. 만약 속도 제한 (rate limit) 발생 시 코드에서 Sonnet 4.6에서 Haiku 4.5로 폴백 (fallback) 한다면, Haiku 호출에는 캐시 기록이 없습니다. 폴백 경로를 캐싱하지 않도록 유지하거나, 모델별로 별도의 캐시를 구축해야 합니다.

## 프롬프트 캐싱을 사용하지 말아야 할 때

캐싱에는 오버헤드 (overhead)가 따릅니다. 다음과 같은 경우에는 캐싱을 건너뛰세요:

- **공유 접두사(shared prefix)가 없는 원샷 호출 (One-shot calls)** — 단일 요청 분류(classification), 일회성 요약(summarization) 등. 1.25배의 쓰기 프리미엄(write premium)은 순전한 손실입니다.
- **변동성이 높은 프롬프트 (High-variability prompts)** — 각 요청마다 상용구(boilerplate)가 다르다면, 아무런 이득 없이 쓰기 프리미엄만 지불하게 됩니다.
- **최소 기준 미만의 프롬프트** — 짧은 프롬프트는 캐싱할 수 없습니다.
- **비용이 이미 무시할 수 있는 수준인 경우** — API 비용으로 월 20달러를 지출한다면, 캐싱을 최적화하기 위한 엔지니어링 시간이 절감되는 비용보다 더 많이 듭니다.

유용한 휴리스틱(heuristic): **안정적인 접두사(stable prefix)가 2,000 토큰 이상이고, 해당 접두사를 사용하여 5분 단위당 3회 이상의 요청을 보낸다면 캐싱하세요.**

## 종합 정리: 프로덕션 체크리스트

2026년에 Claude 연동 기능을 배포하기 전에 다음 목록을 실행하세요:

- [ ] 시스템 프롬프트(System prompt)에 `cache_control`이 설정되었는가
- [ ] 도구 정의(Tool definitions)가 정렬되어 있고 안정적인가
- [ ] 사용자 변수 콘텐츠(User-variable content)가 프롬프트 중간이 아닌 끝에 위치하는가
- [ ] 캐시 통계(`cache_read_input_tokens`)가 로그로 기록되고 대시보드화되어 있는가
- [ ] 캐시 히트율(Cache hit rate)을 모니터링하는가 — 80% 미만으로 떨어지면 알람을 설정하세요
- [ ] 캐싱된 블록에 타임스탬프(timestamps), 요청 ID(request IDs) 또는 무작위 데이터가 주입되지 않았는가
- [ ] 첫 번째 요청의 캐시 쓰기(cache write)가 테스트에서 검증되었는가
- [ ] 폴백 모델 경로(Fallback model paths)가 캐시 부재 상황을 깔끔하게 처리하는가
- [ ] 5분 대 1시간 TTL(Time-to-Live) 선택에 대한 근거가 문서화되었는가

## 마치며

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
1

댓글

0