RSS
AI 자동화

프롬프트 캐싱: 긴 시스템 프롬프트를 10분의 1 가격으로 읽히는 순서 설계

작성자
듀오랩스 대표·5분 읽기

시스템 프롬프트가 2만 토큰인 챗봇이 있다고 해 보겠습니다. 제품 설명서, 응대 규칙, 예시 대화가 들어 있습니다. 사용자가 "배송 언제 와요?"라고 한 줄을 물어도 모델은 매번 2만 토큰을 처음부터 다시 읽고, API는 그만큼 과금합니다.

Claude Sonnet 5.5의 입력 가격은 100만 토큰당 2달러입니다. 2만 토큰이면 호출 한 번에 0.04달러이고, 하루 1만 번이면 400달러입니다. 사용자의 질문 한 줄은 이 비용에서 거의 차지하는 몫이 없습니다.

긴 프롬프트는 줄여야 한다는 오해

이 계산을 보면 시스템 프롬프트를 줄이고 싶어집니다. 예시를 빼고 규칙을 압축합니다. 그런데 그 예시와 규칙은 품질 때문에 넣은 것이라 줄이면 답이 나빠집니다.

프롬프트 캐싱은 다른 답을 줍니다. 길이는 그대로 두고, 매번 똑같은 앞부분을 서버가 기억하게 합니다. 두 번째 호출부터 그 부분은 훨씬 싸게 읽힙니다. 줄여야 할 것은 길이가 아니라 요청마다 달라지는 부분의 위치입니다.

앞부분이 한 글자라도 같아야 하는 조건

캐시는 프롬프트의 앞부분(prefix)이 정확히 같을 때만 맞습니다. Anthropic 문서는 캐시가 도구 정의, 시스템 프롬프트, 메시지 순서로 쌓인다고 설명합니다. 앞 단계가 바뀌면 그 뒤는 전부 다시 계산됩니다. 도구 정의를 하나 고치면 시스템 프롬프트와 대화 전체의 캐시가 함께 무효가 됩니다.

그래서 순서가 곧 설계입니다. 거의 바뀌지 않는 것을 앞에, 자주 바뀌는 것을 뒤에 둡니다. 도구 정의와 규칙과 문서가 앞에 오고, 사용자별 정보와 질문이 맨 뒤에 옵니다.

문서가 흔한 실수로 꼽는 것도 이 순서입니다. 시스템 프롬프트 맨 위에 "현재 시각: 14시 32분 07초"를 넣으면 요청마다 앞부분이 달라집니다. 캐시 쓰기 비용은 매번 내면서 읽기 할인은 한 번도 받지 못합니다. 시각이 꼭 필요하면 맨 뒤 메시지로 옮기면 됩니다.

쓰기 1.25배, 읽기 0.1배의 계산

Anthropic의 기본 캐시는 5분 동안 유지되고, 가격은 기본 입력 단가에 배율을 곱합니다. 캐시에 쓸 때는 1.25배, 캐시에서 읽을 때는 0.1배입니다. 1시간 유지를 고르면 쓰기가 2배가 됩니다. 모델에 따라 읽기가 더 싸서, Opus 5.5는 0.05배, Fable 5.1은 0.025배입니다.

앞의 2만 토큰 예로 계산하면 이렇습니다. Sonnet 5.5에서 캐시 없이 읽으면 호출당 0.04달러입니다. 처음 한 번 캐시에 쓸 때 0.05달러, 이후 읽을 때마다 0.004달러입니다. 5분 안에 100번 호출하면 캐시 없이 4달러, 캐시를 쓰면 약 0.45달러입니다.

손익분기는 생각보다 낮습니다. 쓰기에서 더 낸 0.25배는 읽기 한 번에서 아끼는 0.9배보다 작습니다. 같은 앞부분이 5분 안에 한 번만 다시 쓰여도 이미 이득입니다.

캐시가 걸리지 않는 짧은 프롬프트

캐시에는 최소 길이가 있습니다. Anthropic은 Sonnet 5.5, Opus 5.5 같은 최근 모델에서 512토큰, 모델에 따라 1,024토큰에서 4,096토큰까지 요구합니다. 이보다 짧은 앞부분은 캐시하지 않습니다. 짧은 프롬프트는 애초에 싸니 크게 아쉬울 일은 아닙니다.

캐시 지점(breakpoint)은 요청당 최대 4개까지 둘 수 있습니다. 도구 정의 끝, 시스템 프롬프트 끝, 대화의 마지막 부분처럼 바뀌는 주기가 다른 층마다 하나씩 두는 것이 기본 전략입니다. 가장 간단하게는 요청 최상단에 cache_control을 하나 두면 마지막 블록에 자동으로 지점이 잡히고, 대화가 길어지면 지점도 따라 움직입니다.

OpenAI와 Anthropic의 방식 차이

OpenAI는 캐싱이 기본으로 켜져 있습니다. 개발자가 지점을 표시하지 않아도 1,024토큰 이상의 앞부분이 같으면 자동으로 할인됩니다. GPT-5.6 이후 모델은 캐시된 입력이 0.1배이고, 마지막 사용 후 30분 동안 유지됩니다.

Anthropic은 명시적 표시를 기본으로 하고 자동 방식을 선택지로 둡니다. 쓰기에 1.25배를 받는 대신 무엇을 캐시할지 개발자가 정합니다. 저는 두 방식의 차이가 편의보다 예측 가능성에 있다고 봅니다. 자동 방식은 손댈 것이 없지만, 캐시가 왜 안 맞는지 따질 때 단서가 적습니다.

캐시가 맞았는지 확인하는 법

배포하고 끝내면 안 됩니다. 응답의 usage에는 캐시에서 읽은 토큰(cache_read_input_tokens), 캐시에 쓴 토큰(cache_creation_input_tokens), 캐시 밖에서 처리한 토큰(input_tokens)이 따로 나옵니다.

같은 프롬프트로 두 번 연속 호출했는데 두 번째에도 읽기가 0이라면, 앞부분 어딘가에 요청마다 바뀌는 것이 숨어 있다는 뜻입니다. 시각, 요청 ID, 순서가 바뀌는 목록이 흔한 범인입니다. 저라면 캐시 적중률을 운영 지표로 올려 두겠습니다. 누군가 프롬프트 맨 앞에 한 줄을 더한 날, 비용이 10배로 뛰기 전에 알 수 있습니다.

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.