기타개발지식/풀스택개발

[Claude][운영] batch processing에서 prompt caching hit를 높이려면 공통 system prompt와 작업별 메시지를 어떤 순서로 쪼개나

Sophie_ 2026. 8. 4. 20:17

IT 리서치 노트

[Claude][운영] batch processing에서 prompt caching hit를 높이려면 공통 system prompt와 작업별 메시지를 어떤 순서로 쪼개나

Claude Message Batches에 prompt caching을 붙이면 비용과 처리량을 같이 줄일 수 있지만, 실제 hit는 공통 prefix를 어떻게 쪼개느냐에 크게 좌우된다. 2026년 8월 4일 기준 Anthropic 공식 문서를 다시 보면 batch cache hit는 best-effort이며, automatic caching과 explicit cache breakpoints를 함께 쓸 수 있고, 대부분 모델에서는 cache read tokens가 ITPM에 포함되지 않는다. 이 글은 batch processing에서 prompt caching hit를 높이려면 공통 system prompt와 작업별 메시지를 어떤 순서로 쪼개는 편이 실무적으로 덜 꼬이는지 정리한 것이다.

1. 개요

결론부터 말하면 batch hit를 높이는 가장 빠른 방법은 요청 순서를 바꾸는 것이 아니라 공통 prefix와 변동 tail을 더 분명하게 자르는 것이다. 모든 요청에서 같은 system prompt, 같은 정책 블록, 같은 도메인 문서는 cacheable prefix로 앞에 두고, 요청마다 달라지는 질문과 고객별 변수는 가장 뒤로 미뤄야 한다.

이렇게 하면 cache hit가 best-effort로 흔들리더라도 흔들리는 이유가 더 짧게 드러난다. hit가 낮아도 prefix 설계가 잘못된 것인지, batch가 동시에 처리돼 cache warm 타이밍이 어긋난 것인지, 혹은 thinking/tool 설정이 섞였는지 로그 기준을 잡을 수 있다.

2. 어디서 실제로 막히는가

실무에서 흔한 실패는 세 가지다. 첫째, 긴 공통 system prompt와 작업별 고객 데이터를 한 블록에 같이 넣어 매 요청마다 공통 prefix가 달라진다. 둘째, batch cache hit가 낮으면 무조건 prompt caching 설정이 잘못됐다고 보고 concurrency 특성을 잊는다. 셋째, usage를 볼 때 cache_read_input_tokens와 cache_creation_input_tokens를 따로 보지 않아 어떤 요청이 실제로 miss였는지 설명하지 못한다.

Anthropic 문서는 automatic caching이 마지막 cacheable block까지 자동으로 이동한다고 설명하지만, explicit cache breakpoints도 같이 쓸 수 있다고 덧붙인다. 동시에 Message Batches 문서는 batch cache hit가 best-effort이고 동시성 때문에 30%에서 98%까지 흔들릴 수 있다고 적는다. 즉 지금 문제는 'cache_control을 켰는가'보다 '어떤 블록을 공통 prefix로 고정했는가'와 'batch 동시성으로 생긴 흔들림을 usage에서 어떻게 구분하는가'에 더 가깝다.

rate limits 문서도 중요한 힌트를 준다. 대부분 모델에서 cache_read_input_tokens는 ITPM에 잡히지 않으므로, 공통 prefix를 잘 캐시하면 비용뿐 아니라 effective throughput도 오른다. 반대로 공통 prefix 설계가 엉키면 배치가 길어지고 queue와 spend가 같이 늘어난다.

  • 증상: 같은 batch인데 일부 요청만 cache_creation이 계속 커진다.
  • 실패: 공통 system prompt와 작업별 데이터를 한 cacheable block에 섞는다.
  • 막힘: batch hit가 낮으면 concurrency보다 설정 오타만 의심한다.
  • 누락: input, cache_creation, cache_read 세 필드를 같이 기록하지 않는다.
질문 먼저 볼 곳 실무 판단
공통 prefix가 진짜 고정인가 system/document 블록 구성 변수 필드를 tail로 뺀다
hit가 낮은 이유가 설계 문제인가 batch 동시성, warm timing, best-effort 특성 동일 prefix라도 일부 miss는 허용한다
throughput이 왜 안 오르는가 cache_read_input_tokens / ITPM uncached tail이 너무 긴지 본다

3. 실무에서 적용하는 순서

가장 짧은 적용 순서는 다섯 단계다. 먼저 배치 전체에 공통인 system prompt와 긴 참조 문서를 분리한다. 두 번째로 그중에서도 자주 바뀌지 않는 블록만 cacheable prefix로 묶는다. 세 번째로 작업별 customer 변수와 질문은 항상 마지막 user block으로 보낸다. 네 번째로 usage에서 input_tokens, cache_creation_input_tokens, cache_read_input_tokens를 모두 남긴다. 다섯 번째로 batch hit 해석은 '평균 hit 하나'가 아니라 shared prefix hit, tail length, concurrency timing 세 칸으로 나눠 본다.

  1. 공통 system prompt와 공통 문서를 먼저 분리한다.
  2. 자주 바뀌지 않는 블록만 cacheable prefix로 둔다.
  3. 작업별 질문과 고객별 변수는 마지막 tail로 보낸다.
  4. usage의 세 입력 필드를 모두 로그에 남긴다.
  5. hit 해석은 설계, tail 길이, concurrency timing으로 나눠 본다.

thinking과 tool-use가 섞이면 한 칸 더 본다. thinking 문서는 tool result를 포함한 follow-up 요청에서 thinking blocks가 같이 캐시될 수 있다고 설명한다. 따라서 batch 설계 자체는 공통 prefix를 잘랐더라도, 같은 묶음 안에서 thinking 설정이나 tool 흐름이 흔들리면 hit가 달라질 수 있다. 이때는 prompt diff보다 settings diff와 turn type diff를 먼저 기록하는 편이 빠르다.

운영 로그를 남길 때는 shared prefix 버전을 저장하고, 같은 배치 안에서 요청별 tail 길이를 조회하고, cache_read와 cache_creation 수치를 비교하고, thinking 설정이 바뀐 run_id를 확인하고, tool 경로가 달라진 요청을 따로 표시하는 식으로 기록하면 된다. 이렇게 입력 위치와 로그 형식을 고정해 두면 다음 배치에서 어떤 필드를 다시 입력하고 어떤 값을 비교해야 하는지 바로 보인다.

batch_cache_record:
shared_prefix_version=2026-08-04-r1
tail_template=customer_prompt,task_id,locale
usage.input_tokens=...
usage.cache_creation_input_tokens=...
usage.cache_read_input_tokens=...
thinking_mode=adaptive|none
tool_path=none|server_tool|client_tool

이 정도만 남겨도 같은 배치에서 어떤 요청이 공통 prefix를 잘 재사용했고, 어떤 요청이 tail이 길어서 miss가 커졌는지 금방 드러난다. hit가 100%가 아니어도 원인을 설명할 수 있으면 운영은 훨씬 짧아진다.

4. 공식 문서와 예시 화면으로 확인하기

첫 자료는 Claude prompt caching 문서의 automatic caching 설명이다. 공통 prefix를 매 요청마다 다시 붙여도 마지막 cacheable block까지 자동으로 이동시켜 읽어 준다는 점을 먼저 잡아야 한다.

Claude prompt caching 문서는 top-level cache_control 하나로 자동 cache breakpoint가 마지막 cacheable block까지 이동한다고 설명한다.
Claude prompt caching 문서는 top-level cache_control 하나로 자동 cache breakpoint가 마지막 cacheable block까지 이동한다고 설명한다.

이 성질 덕분에 batch에서도 공통 system prompt를 매 요청마다 복사하는 것은 허용되지만, 어디까지를 공통 prefix로 둘지 설계하지 않으면 hit가 흔들린다. 이미 automatic caching과 explicit breakpoints 분기 글이 큰 기준을 다뤘다면, 이번 글은 batch 요청 묶음 안에서 그 기준을 어떻게 배치할지에 더 가깝다.

두 번째 자료는 explicit cache breakpoints 구간이다. 공통 system prompt와 문서 블록을 어디까지 고정하고, 어떤 블록을 작업별로 뒤에 붙일지 세밀하게 나눌 수 있다.

Claude는 block 단위 cache_control로 바뀌는 구간과 고정 구간을 직접 분리할 수 있다고 설명한다.
Claude는 block 단위 cache_control로 바뀌는 구간과 고정 구간을 직접 분리할 수 있다고 설명한다.

batch hit를 높이고 싶다면 이 기능을 '많이 넣을수록 좋다'가 아니라 '공통 prefix와 변동 tail을 분리하는 최소 단위'로 써야 한다. 공통 규칙과 작업별 변수의 경계를 잘못 잡으면 오히려 캐시 조각이 늘고 어떤 요청이 왜 miss가 났는지 설명이 어려워진다.

세 번째 자료는 Message Batches 문서의 prompt caching 구간이다. Anthropic은 batch cache hit가 best-effort이며 동시성과 트래픽 패턴에 따라 30%에서 98%까지 흔들릴 수 있다고 적고 있다.

Claude batch processing 문서는 prompt caching을 지원하지만 cache hit는 best-effort이며 트래픽 패턴에 따라 크게 달라질 수 있다고 설명한다.
Claude batch processing 문서는 prompt caching을 지원하지만 cache hit는 best-effort이며 트래픽 패턴에 따라 크게 달라질 수 있다고 설명한다.

즉 batch에서 hit가 낮다고 해서 곧바로 cache_control이 깨졌다고 단정하면 안 된다. 요청 묶음 자체가 동시에 처리되므로, 공통 prefix를 잘 설계해도 순서와 타이밍 때문에 기대치보다 낮게 나올 수 있다.

네 번째 자료는 rate limits 문서의 cache-aware ITPM 구간이다. 대부분 모델에서 cache_read_input_tokens는 ITPM에 포함되지 않고, uncached input과 cache creation만 rate limit에 잡힌다.

Claude rate limits 문서는 대부분 모델에서 cache read tokens가 ITPM에 포함되지 않아 effective throughput을 올릴 수 있다고 설명한다.
Claude rate limits 문서는 대부분 모델에서 cache read tokens가 ITPM에 포함되지 않아 effective throughput을 올릴 수 있다고 설명한다.

그래서 batch hit를 높이는 목적은 단순 비용 절감에 그치지 않는다. 공통 prefix를 캐시로 읽게 만들면 같은 tier에서도 더 많은 total input을 처리할 수 있어, batch queue를 더 짧게 유지하는 효과까지 생긴다.

실무에서 가장 유용한 자료는 공통 prefix와 작업별 tail을 나누는 표다. 공통 system prompt, 긴 정책 문서, 태스크별 질문을 한 줄로 분리해야 같은 배치 안에서 hit가 덜 흔들린다.

Claude batch 요청에서 어떤 블록을 공통 prefix로 두고 어떤 블록을 작업별 tail로 뺄지 정리한 표다.
Claude batch 요청에서 어떤 블록을 공통 prefix로 두고 어떤 블록을 작업별 tail로 뺄지 정리한 표다.

이 표를 기준으로 하면 요청마다 달라지는 질문, customer-specific 변수, short-lived thinking note를 공통 블록에 섞는 실수를 줄일 수 있다. 같은 가지의 앞단인 5분 TTL과 1시간 TTL 분기 글과 thinking config와 tool_choice cache-miss 글까지 같이 보면 배치형 cache 설계와 miss triage가 연결된다.

마지막 자료는 batch 요청 형태 예시다. 공통 system block은 맨 앞에 두고, 작업별 메시지는 요청마다 가장 뒤에 붙여야 cache read와 uncached tail이 비교적 선명하게 갈린다.

Claude batch 요청에서 공통 system prompt와 작업별 tail을 분리한 예시다.
Claude batch 요청에서 공통 system prompt와 작업별 tail을 분리한 예시다.

이 정도만 지켜도 왜 특정 배치만 cache_creation이 커졌는지 역추적이 쉬워진다. 공통 prefix를 앞에 고정하고 작업별 메시지를 뒤에만 붙이는 습관이 핵심이다.

5. 주의사항과 리스크

첫 번째 리스크는 공통 prompt를 너무 잘게 쪼개 breakpoint만 늘리는 것이다. 두 번째는 batch cache hit가 best-effort라는 사실을 잊고, 일부 miss를 전부 설계 실패로 오해하는 것이다. 세 번째는 rate limit 이점을 놓친 채 비용 숫자만 보고 prefix 설계를 바꾸는 것이다.

운영 전에는 최소한 shared prefix 버전, tail 필드 목록, usage 3종, thinking/tool 설정을 같은 레코드로 남기는 편이 좋다. 그래야 cache hit가 낮았던 날도 무조건 문서를 다시 자르기보다 동시성이나 설정 차이를 먼저 의심할 수 있다.

  • 공통 prefix는 길이보다 안정성이 우선이다.
  • batch hit는 best-effort라 일부 miss를 허용해야 한다.
  • usage는 input, cache_creation, cache_read를 같이 본다.

6. 결론

Claude batch processing에서 prompt caching hit를 높이려면 cache_control을 더 많이 넣는 것보다 공통 prefix와 작업별 tail을 더 명확하게 나누는 편이 효과적이다. 공통 system prompt와 참조 문서는 앞에 고정하고, 작업별 질문과 고객별 변수는 뒤로 밀고, usage 필드와 settings diff를 함께 남기면 hit가 완벽하지 않아도 운영 판단은 훨씬 쉬워진다.

  • shared prefix는 공통 system prompt와 공통 문서만 남긴다.
  • task별 변수는 항상 tail로 분리한다.
  • usage 3종과 settings diff를 같이 저장한다.

같은 가지의 관련 글로는 5분 TTL과 1시간 TTL 분기 글, automatic caching과 explicit breakpoints 글, tool use 루프 usage 읽는 글, thinking config와 tool_choice cache miss 글이 있다. 그 위에 이번 배치형 prefix 분리를 얹으면 비용, 처리량, miss triage가 한 줄로 이어진다.

이 글을 읽고 바로 이어서 보면 좋은 후속편은 긴 정책 블록은 1시간 TTL로 두고 짧은 요약과 user-tail은 5분 TTL로 섞을 때 billing 메모를 어떻게 남기는지 정리한 글이다. 여기서는 batch 분리 순서가 맞는 상황에서 mixed TTL 비용 기록을 어떤 필드와 표로 남길지 더 좁게 다룬다.

배치형 prefix를 이미 얇게 나눴다면 그다음으로 볼 글은 Claude Opus 5에서 prompt caching 최소 길이가 512 tokens로 내려간 뒤 prefix 재분리 기준을 다시 잡는 글이다. 예전에는 임계값 때문에 한 덩어리로 묶었던 500~800 token대 블록을 Opus 5에서는 어디까지 독립 cache block으로 다시 분리할지 이어서 판단할 수 있다.

7. 참고 링크

  1. https://platform.claude.com/docs/en/build-with-claude/prompt-caching
  2. https://platform.claude.com/docs/en/build-with-claude/batch-processing
  3. https://platform.claude.com/docs/en/api/rate-limits
  4. https://platform.claude.com/docs/en/build-with-claude/thinking