CPN 한국어 자습서 · 러닝패스 2 / 4 — Building with the Claude API
Claude의 기능
Rules of prompt caching
캐싱의 개념을 잡았으니, 이제 Claude에서 캐싱을 실제로 켜고 쓰는 규칙을 봅니다. 캐시 breakpoint를 어디에 두는지에 따라 어디까지 캐시되는지, 후속 요청이 왜 적중하거나 무효가 되는지, 그리고 최소·최대 같은 제약을 하나씩 정리합니다.
Stephen Grider · Anthropic 기술 스태프
이론을 이해했으니, 이제 Claude에서 프롬프트 캐싱이 실제로 어떻게 동작하는지 살펴봅니다. 핵심 아이디어는 지난 장과 같습니다. 처음 요청을 보내면 Claude가 그 메시지를 처리하고, 그 작업을 임시 캐시에 저장합니다. 그다음 미래의 어느 시점에 똑같은 메시지를 포함한 후속 요청을 보내면, Claude는 그 메시지를 다시 처리하는 대신 캐시를 들여다보고 이미 저장해 둔 작업을 불러옵니다.
분명히 해 두자면, 캐시에 저장된 작업은 영원히 남지 않습니다. 딱 1시간 동안만 보관됩니다. 프롬프트 캐싱은 같은 콘텐츠를 계속 반복해서 보낼 때 가장 유용합니다. 본질적으로 2단계 과정이라서, 먼저 처음 요청으로 캐시에 데이터를 써 넣어야 그 뒤의 후속 요청들만 미리 해 둔 작업의 이득을 볼 수 있기 때문입니다.
이 캐싱 시스템은 Claude에서 기본으로 켜져 있지 않습니다. 캐싱을 켜려면 메시지 안의 한 블록에 캐시 breakpoint를 수동으로 추가해야 합니다. 하는 일은 그 작은 cache_control 필드를 넣는 것뿐입니다. 다만 여기에 작은 팁이 하나 있습니다.
이 코스 내내 우리는 텍스트 블록을 짧게 쓰는 단축형을 자주 썼습니다. user 메시지에 텍스트가 조금만 있으면 content 필드에 문자열을 바로 대입할 수 있죠. 텍스트 블록을 쓰는 또 다른 방법은 content에 리스트를 주고, 그 안에 type이 text이고 text 필드에 실제 텍스트가 든 딕셔너리를 넣는 롱폼입니다. 그동안 롱폼을 잘 쓰지 않았지만, cache_control을 쓰려면 — 즉 캐싱을 켜려면 — 이 텍스트 블록을 롱폼으로 써야 합니다. 그래야 cache_control 필드를 붙일 자리가 생깁니다. 단축형에는 그걸 넣을 자리가 없습니다.
블록에 breakpoint를 넣으면, 요청 안의 모든 콘텐츠가 그 breakpoint까지(그 블록 포함) 캐시됩니다. 첫 블록에 breakpoint가 있으면 그 텍스트를 처리한 작업이 캐시에 저장되고, breakpoint 뒤의 작업은 캐시되지 않습니다. 나중에 후속 요청을 보내면 Claude는 캐시를 보고 그 첫 블록 처리 작업을 찾아 꺼내 씁니다.
한 가지 명심할 점은, 후속 요청은 그 breakpoint까지의 콘텐츠가 완전히 동일해야 한다는 것입니다. 예를 들어 breakpoint가 있던 첫 텍스트 블록에 “please”라는 단어 하나만 더해도, 더 이상 콘텐츠가 동일하지 않으므로 캐시가 쓰이지 않습니다. 그러면 Claude는 그 블록과 그 앞의 모든 콘텐츠를 다시 처리합니다.
캐시 breakpoint는 여러 메시지와 여러 블록에 걸칠 수 있습니다. user, assistant, user 순으로 보내고 마지막 메시지의 한 블록에 breakpoint를 두면, 그 블록까지(포함)의 모든 것 — 세 메시지를 처리한 작업 — 이 캐시에 저장됩니다. 후속 요청에서 그 breakpoint까지가 동일하면 캐시에서 작업을 꺼내 씁니다.
breakpoint는 텍스트 블록에만 붙이는 게 아닙니다. image 블록, tool_use, tool_result 같은 거의 모든 종류의 블록에 붙일 수 있고, tool 스키마와 system 프롬프트에도 붙일 수 있습니다. 많은 애플리케이션에서 system 프롬프트와 tool 목록은 잘 바뀌지 않기 때문에, 이들은 breakpoint를 두기에 아주 좋은 자리입니다.
정리하면 breakpoint는 tool 스키마, system 프롬프트, 메시지 블록에 둘 수 있습니다. 그런데 이건 세 개의 별도 캐시 시스템이 아닙니다. tools, system, messages를 넣으면 무대 뒤에서 이들이 하나로 합쳐져 Claude에 들어가는데, 그 순서가 정해져 있습니다 — 먼저 tools, 그다음 system, 그다음 messages입니다. 그래서 마지막 tool에 breakpoint를 두면 그 tool까지만 캐시되고 system과 messages는 캐시되지 않습니다. 이때 그 뒤의 메시지를 바꿔도 tool 목록은 미리 캐시돼 있으니 그만큼 작업을 아낍니다.
breakpoint는 최대 4개까지 둘 수 있습니다. 마지막 tool 스키마와 어떤 assistant 메시지에 각각 두는 식이죠. 그 뒤의 user 메시지를 바꾸면 tools·system·앞쪽 메시지 처리 작업을 재사용하고, 첫 user 메시지를 바꾸면 그 아래 캐시는 무효가 되지만 tool 목록 캐시는 여전히 살아 있습니다. 어디에 둘지는 결국 애플리케이션에 달렸습니다.
마지막으로, 캐싱에는 최소 콘텐츠 길이가 있습니다. 어떤 콘텐츠를 캐시하려면 최소 1,024 토큰 이상이어야 합니다. 예를 들어 “hi there”라는 짧은 텍스트에 breakpoint를 둬도 1,024 토큰에 한참 못 미치므로 캐시에 써지지 않습니다. 그 텍스트 블록을 500번 복제하면 1,024 토큰을 넘겨, 그제야 이 블록 리스트가 캐시됩니다.
이 장에서 배우는 것What you'll learn
약 9분cache_control:{type:"ephemeral"} = 캐시 breakpoint. 기본은 꺼져 있다
단축형 문자열엔 못 붙임 → 롱폼 텍스트 블록(리스트+딕셔너리)으로 써야 자리가 생긴다
breakpoint 까지(포함) 캐시 — 후속 요청은 그 지점까지 완전히 동일해야 적중
텍스트뿐 아니라 image·tool_use·tool_result·tool 스키마·system에도 가능
합쳐지는 순서: tools → system → messages (마지막 tool에 두면 tools만 캐시)
최대 4개 breakpoint · 최소 1,024 토큰 이상이어야 캐시됨
캐싱은 기본으로 꺼져 있습니다. 켜려면 메시지 안의 한 블록에 캐시 breakpoint — 즉 cache_control 필드를 수동으로 추가합니다. 값은 {type:"ephemeral"}입니다.
한 가지 걸림돌이 있습니다. 그동안 자주 쓴 단축형(content에 문자열을 바로 대입)에는 cache_control을 붙일 자리가 없습니다. 그래서 롱폼 — content를 리스트로 두고 {type:"text", text:…} 딕셔너리를 넣는 형식 — 으로 써야 합니다. 그래야 같은 딕셔너리 안에 cache_control을 넣을 수 있습니다.
# 단축형 — content가 문자열. cache_control 붙일 자리가 없다 messages = [{ "role": "user", "content": "여기에 아주 긴 문서…", }] # 롱폼 — content가 리스트. text 블록에 cache_control 추가 messages = [{ "role": "user", "content": [ { "type": "text", "text": long_text, "cache_control": {"type": "ephemeral"}, # ← 캐시 breakpoint } ], }]
캐싱을 켜려면 롱폼 텍스트 블록이 필요합니다. 단축형 문자열로는 breakpoint를 둘 자리가 없습니다.
블록에 breakpoint를 넣으면, 요청 안의 모든 콘텐츠가 그 breakpoint까지(그 블록 포함) 캐시됩니다. 그 뒤의 콘텐츠는 캐시되지 않습니다.
대신 후속 요청은 그 breakpoint까지가 완전히 동일해야 적중합니다. 캐시됐던 텍스트 블록에 “please”라는 단어 하나만 더해도 콘텐츠가 달라져 캐시가 쓰이지 않고, 그 블록과 그 앞 전체를 다시 처리합니다. breakpoint는 여러 메시지·여러 블록에 걸쳐 둘 수 있습니다(예: user→assistant→user의 마지막 블록에 두면 세 메시지 작업이 모두 캐시).
“완전히 동일”이 핵심입니다. breakpoint 지점까지 한 글자라도 달라지면 그 지점부터 무효가 되어 다시 쓰기가 일어납니다.
breakpoint는 텍스트뿐 아니라 image·tool_use·tool_result, 그리고 tool 스키마와 system 프롬프트에도 붙일 수 있습니다. system과 tools는 잘 바뀌지 않아 캐시 명당입니다.
# tool 스키마와 system 프롬프트에도 붙일 수 있다(잘 안 바뀌는 캐시 명당) tools = [ schema_a, { **schema_b, "cache_control": {"type": "ephemeral"}, # 마지막 tool까지 캐시 }, ] system = [ { "type": "text", "text": system_prompt, "cache_control": {"type": "ephemeral"}, } ] # 합쳐지는 순서: tools → system → messages
이들은 별도 캐시가 아닙니다. 요청은 tools → system → messages 순서로 한 줄로 합쳐집니다. 그래서 마지막 tool에 breakpoint를 두면 tools만 캐시되고, 그 뒤(system·messages)를 바꿔도 tools 캐시는 살아 있습니다. 아래 위젯에서 직접 확인해 보세요.
tool 스키마 #1
tools[0] · ~900 토큰
tool 스키마 #2 (마지막)
tools[-1] · ~800 토큰
system 프롬프트
system · ~6000 토큰
user — 긴 문서 (롱폼)
messages[0] · ~2200 토큰
assistant 응답
messages[1] · ~300 토큰
user — "hi there" (짧음)
messages[2] · ~6 토큰
breakpoint 까지(포함) 위쪽 전체가 캐시됩니다. 캐시된 범위 안의 블록을 변경하면 그 지점부터 무효가 되어 다시 쓰기가 일어나고, 캐시 범위 뒤를 바꾸면 여전히 적중합니다. 짧은(1,024토큰 미만) 블록에만 둔 breakpoint는 캐시되지 않습니다.
순서
tools → system → messages
한 줄로 합쳐진다. 앞쪽(tools)에 둘수록 더 안정적으로 적중한다.
개수
최대 4개
tool·system·메시지 곳곳에 나눠 둘 수 있다. 위치는 애플리케이션에 따라.
길이
최소 1,024 토큰
"hi there"처럼 짧으면 캐시되지 않는다. 그만큼 길어야 써진다.
유지
약 1시간
저장된 작업은 영구가 아니다. 시간이 지나면 사라진다.
cache_control:{type:"ephemeral"}가 캐시 breakpoint — 기본은 꺼져 있다.Q1단축형 문자열 content에는 cache_control을 붙이지 못하는 이유는?
롱폼 텍스트 블록({type:"text", text:…})으로 써야 같은 딕셔너리 안에 cache_control을 넣을 자리가 생깁니다.
Q2breakpoint까지 캐시된 뒤, 후속 요청에서 그 지점 앞 텍스트에 “please”를 한 단어 더했습니다. 결과는?
적중하려면 breakpoint 지점까지 “완전히 동일”해야 합니다. 한 글자만 달라져도 그 지점부터 무효가 됩니다.
Q3마지막 tool 스키마에만 breakpoint를 뒀습니다. 그 뒤 메시지를 바꾸면?
합쳐지는 순서가 tools → system → messages이므로, 마지막 tool에 둔 breakpoint는 tools까지만 캐시합니다. 뒤쪽 메시지를 바꿔도 tools 캐시는 살아 있습니다.
규칙을 잡았으니, 이제 코드에서 캐싱을 켜고 usage 토큰으로 적중을 확인해 봅니다. → 프롬프트 캐싱 실전
전 코스는 계속 무료입니다. 등록하면 이 코스의 남은 76개 레슨을 끝까지 읽을 수 있습니다.
이미 등록하셨다면 그때 쓰신 이메일을 넣어 주세요.