프롬프트 캐싱을 켰지만 아무런 이득도 보지 못했습니다. 사실 OpenAI API 청구 금액이 약 4분의 1 정도 늘어났습니다. 원인은 매 요청마다 바뀌는 단 한 줄의 코드, 바로 시스템 프롬프트에 포함된 타임스탬프였습니다.
LLM 제공업체는 토큰 처리 비용을 절감할 수 있도록 개발자가 프롬프트 조각을 캐싱할 수 있게 해줍니다. 캐시 읽기(hit)는 일반 요금의 10분의 1 수준으로 매우 저렴하지만, 캐시 쓰기(miss)는 일반 가격의 약 1.25배가 부과됩니다. 만약 쓰기가 발생했지만 캐싱된 조각이 한 번도 읽히지 않는다면, 추가된 25%의 비용은 낭비되는 셈입니다. 타임스탬프 때문에 프롬프트가 기존 캐시 항목과 일치하지 않게 되면서 정확히 이런 일이 발생했습니다.
캐싱이 역효과를 낼 수 있는 이유
프롬프트 캐싱은 캐싱된 부분의 정확한 바이트 시퀀스를 일치시키는 방식으로 작동합니다. 제공업체는 입력을 해싱합니다. 만약 해시가 저장된 항목과 일치하면 시스템은 이전 계산을 재사용하고 저렴한 읽기 요금을 적용합니다. 단 한 글자라도 차이가 나면 일치하지 않는 것으로 간주되어 새로운 계산이 강제되며, 더 높은 쓰기 요금이 부과됩니다.
제 경우 시스템 프롬프트는 다음과 같이 시작되었습니다:
Current session started: 2026-07-14T09:41:07Z
API 호출마다 타임스탬프가 업데이트되었기 때문에 요청의 처음 몇 바이트가 결코 동일할 수 없었습니다. 제공업체는 각 호출을 새로운 캐시 항목으로 취급하여 쓰기 프리미엄을 부과했고, 읽기는 한 번도 기록되지 않았습니다. 그 결과 cache_read_input_tokens는 0에 머물러 있는 반면 cache_creation_input_tokens는 꾸준히 상승했는데, 이는 캐시가 전혀 작동하지 않고 있다는 명확한 신호였습니다.
깨진 캐시를 식별하는 방법
API에서 제공하는 사용 로그에는 두 가지 핵심 카운터가 있습니다:
- cache_creation_input_tokens – 쓰기를 유발한 토큰.
- cache_read_input_tokens – 읽기를 통해 혜택을 받은 토큰.
전자가 증가하고 후자가 정체되어 있다면 캐시가 재사용되지 않고 있는 것입니다. 간단한 확인 방법은 동일한 요청을 두 번 반복하는 것입니다. 캐시가 제대로 작동한다면 두 번째 호출에서 읽기 토큰이 급증해야 합니다.
문제 해결 방법
해결 방법은 간단합니다. 캐싱되는 영역이 호출 간에 *정적(static)*이 되도록 보장하면 됩니다. 다음 두 가지 규칙을 따르세요:
- 불변(immutable) 콘텐츠를 먼저 배치하세요. 시스템 프롬프트, 도구 정의 또는 절대 변하지 않는 지침은 요청의 앞부분 바이트를 차지해야 합니다.
- 가변(mutable) 콘텐츠를 마지막에 추가하세요. 타임스탬프, 사용자 생성 텍스트, 요청 ID 또는 호출마다 변하는 데이터는 캐싱된 세그먼트 뒤에 와야 합니다.
단 한 글자만 바뀌어도 해시가 변경되어 캐시 미스가 지속됩니다. 타임스탬프가 마지막에 위치하도록 프롬프트를 재배치하면 캐시 적중률이 회복되고 청구 금액도 예상했던 낮은 수준으로 돌아옵니다.
캐싱이 실제로 도움이 되는 경우
프롬프트 캐싱은 동일한 지침 세트가 여러 번 재사용되는 시나리오에서 빛을 발합니다:
- 에이전트 루프(Agent loops): AI가 고정된 도구 세트를 반복적으로 호출하는 경우.
- 채팅 세션: 사용자의 최신 쿼리만 바뀌고 길고 정적인 문서를 참조하는 경우.
- 대량 데이터 추출: 동일한 파싱 프롬프트를 많은 레코드에 적용하는 경우.
매번 새로운 컨텍스트가 포함되는 단발성 호출(예: 고유한 서문이 포함된 일회성 질문)의 경우, 캐싱은 아무런 이득이 없으며 요청이 의도치 않게 쓰기를 유발할 경우 오히려 비용이 추가될 수 있습니다.
숨겨진 함정
프롬프트 자체가 정적이라 하더라도, 요청이 하류(downstream) 단계에서 변경될 수 있습니다:
- 프록시 또는 애그리게이터(Aggregators): 순서를 바꾸거나 공백을 삽입하면 바이트 단위의 일치가 깨질 수 있습니다.
- 게이트웨이 서비스: 인증 헤더를 앞에 붙이거나 JSON 형식을 수정하면 의도치 않게 캐싱된 조각이 변경될 수 있습니다.
게이트웨이를 통해 동일한 요청을 두 번 보내고 읽기 카운터를 확인하여 캐싱 경로가 온전하게 유지되는지 테스트하는 것이 도움이 됩니다.
더 넓은 관점에서의 비용 구조
쓰기에 대한 25% 추가 요금은 캐싱 사용에 대한 벌칙이 아닙니다. 이는 향후 재사용을 위해 조각을 저장하는 데 필요한 추가 컴퓨팅 비용을 반영한 것입니다. 캐시 적중(hit)이 발생하면 비용은 급격히 떨어지며, 종종 일반 요금의 일부 수준까지 낮아집니다. 핵심은 시스템이 실제로 캐시를 적중하게 만드는 것입니다. 그렇지 않으면 절감 효과 없이 프리미엄 요금만 지불하게 됩니다.
반론: 캐싱은 죽지 않았다
일부 개발자들은 정적 프롬프트와 동적 프롬프트 부분을 관리하는 복잡성이 비용 절감 효과보다 크다고 주장합니다. 하지만 이러한 관점은 많은 프로덕션 파이프라인이 이미 설정(정적)과 사용자 데이터(동적)를 분리하여 운영하고 있다는 사실을 간과하고 있습니다. 프롬프트를 이에 맞춰 구조화하면, API 초기 개발자들이 혜택을 입었던 것과 동일한 캐싱 메커니즘을 추가 노력 없이 활용할 수 있습니다. 여기서 발생하는 트레이드오프는 프롬프트 설계 시 약간의 규칙을 준수해야 한다는 점이지, 기술의 근본적인 결함이 아닙니다.
다음에 확인해야 할 사항
- 사용량 대시보드에서 두 개의 캐시 카운터를 매주 모니터링하세요.
- 프롬프트 구성을 점검하여 가변적인 요소가 캐시된 블록 뒤에 위치하는지 확인하세요.
- 실제 절감액을 수치화하기 위해 대표적인 워크로드에 대해 캐싱 적용 여부에 따른 A/B 테스트를 실시하세요.
- 프록시 전후의 원시 요청 페이로드를 비교하여 게이트웨이를 검증하세요.
핵심 요약
프롬프트 캐싱은 캐시된 세그먼트가 호출 시마다 완전히 동일할 때만 LLM API 비용을 대폭 절감할 수 있습니다. 프롬프트 시작 부분에 잘못된 타임스탬프나 기타 동적 토큰이 포함되면 매번 비용이 많이 드는 쓰기 작업이 강제되어 비용이 불어납니다. 정적 지침을 앞부분에 배치하고 변경되는 데이터를 뒷부분으로 배치함으로써, 캐시가 제 역할을 다하게 하고 비용을 효과적으로 통제할 수 있습니다.
