프롬프트 캐싱 비용 계산, 5분 TTL 손익분기 정리

3줄 요약
- 같은 프리픽스를 TTL 안에 다시 쓰면 5분 캐시는 두 번째 호출부터, 1시간 캐시는 세 번째 호출부터 싸집니다. 공식 문서가 배율로 못 박아 둔 값이라 계산이 단순합니다.
- 재사용 간격이 TTL을 넘어가면 히트가 0회가 되고 쓰기 배율만 남습니다. 이 구간에서는 5분 캐시가 미캐시보다 25%, 1시간 캐시가 100% 더 비쌉니다.
- 경계는 하루에 몇 번 도느냐가 아니라 TTL 안에 몇 번 도느냐입니다. 제 파이프라인의 슬롯 간격은 5분의 59.3배였습니다.
1.25배. 2배. 0.1배. 그리고 5분과 1시간.
프롬프트 캐싱에서 실제로 외워야 하는 숫자는 이 다섯 개가 거의 전부입니다. 앞의 세 개만 놓고 계산하면 "두 번만 재사용해도 이득"이라는 답이 나오는데요, 저도 그렇게 계산해 두고 예약 작업 파이프라인에 캐싱을 붙일 준비를 했습니다.
붙이기 전에 슬롯 간격을 한 번 재 봤습니다. 뒤의 두 숫자가 앞의 세 숫자를 통째로 무효로 만들고 있었거든요. 배율 계산은 맞았는데 그 계산을 적용할 자격이 없는 구조였습니다.
배율 네 개가 정하는 것
Anthropic 문서는 캐싱 비용을 기본 입력 토큰 가격 대비 배율로 정의합니다. 절대 금액이 아니라 배율이라 모델이 바뀌어도 계산 구조가 그대로입니다.
| 연산 | 배율 | 유효 기간 |
|---|---|---|
| 기본 입력 | 1.0x | — |
| 5분 캐시 쓰기 | 1.25x | 5분 |
| 1시간 캐시 쓰기 | 2.0x | 1시간 |
| 캐시 읽기(히트) | 0.1x | 직전 쓰기와 동일 |
배율만 보면 읽기가 압도적으로 쌉니다. 열 번 읽으면 한 번 보내는 값이니까요. 문제는 쓰기 쪽에 얹히는 25%와 100%를 몇 번의 읽기로 갚느냐입니다.
여기서 배율이라는 표현을 그대로 받아들이는 편이 낫습니다. 절대 금액은 모델마다 다르고 예고 없이 움직입니다. 같은 문서에 Sonnet 5의 도입가 $2/$10이 정식가가 되었고 9월 1일로 예고됐던 $3/$15 인상은 없던 일이 되었다는 안내가 붙어 있습니다.
한 가지 예외는 있습니다. Fable 5.1과 Mythos 5.1은 캐시 읽기가 0.1배가 아니라 0.025배입니다. 경계값은 5분 1.2564, 1시간 2.0256으로 조금 내려가는데, 정수로 끊으면 2회와 3회라 결론은 아래 계산과 같습니다.
손익분기는 대수적으로 떨어집니다
같은 프리픽스를 N회 보낼 때, 캐시를 쓰면 쓰기 1회에 읽기 N−1회입니다.
# 캐시 사용 비용 = 쓰기배율 + 읽기배율 × (N-1)
# 미캐시 비용 = 1.0 × N
# 두 식이 교차하는 N을 구합니다
for name, w in (("5분", 1.25), ("1시간", 2.0)):
r = 0.1
boundary = (w - r) / (1.0 - r) # 캐시가 미캐시보다 싸지는 경계
print(f"{name} TTL → N > {boundary:.4f} 이므로 최소 {int(boundary) + 1}회")
# 5분 TTL → N > 1.2778 이므로 최소 2회
# 1시간 TTL → N > 2.1111 이므로 최소 3회
값을 직접 대입해도 같습니다.
| 재사용 횟수 N | 미캐시 | 5분 캐시 | 1시간 캐시 |
|---|---|---|---|
| 1 | 1.00x | 1.25x (손해) | 2.00x (손해) |
| 2 | 2.00x | 1.35x (이득) | 2.10x (손해) |
| 3 | 3.00x | 1.45x (이득) | 2.20x (이득) |
| 5 | 5.00x | 1.65x (이득) | 2.40x (이득) |
문서도 같은 결론을 문장으로 적어 두었습니다. Anthropic 가격 문서는 캐시 히트가 표준 입력가의 10%이므로 "5분은 한 번 읽으면, 1시간은 두 번 읽으면 본전"이라고 명시합니다. 제 계산과 어긋나지 않아 여기까지는 그대로 믿고 갔습니다.
문턱이 이렇게 낮으면 안 켤 이유가 없어 보입니다
두 번만 재사용하면 이득이라는 건 문턱이라고 부르기도 민망한 값입니다. 에이전트 한 세션은 도구를 부르고 결과를 받는 왕복만 수십 번이고, 그 왕복마다 시스템 프롬프트와 도구 정의가 통째로 다시 전송됩니다. 대화형 워크로드라면 N은 쉽게 두 자리가 됩니다.
그래서 저는 제 예약 작업 3개에도 당연히 이득일 거라고 봤습니다. 08시·13시·17시 슬롯이 매번 같은 공유 문서 세 개를 읽으니 N은 최소 3이었으니까요.
문서도 낮은 문턱을 전제로 쓰여 있습니다. 브레이크포인트를 추가하는 것 자체에는 비용이 없고, 최상위에 필드 하나만 넣는 자동 캐싱 방식이 권장 출발점으로 소개됩니다. 읽는 쪽에서 "일단 켜라"로 받아들이기 쉬운 서술입니다.
그런데 히트가 한 번도 나지 않았습니다
N만 세고 간격을 안 셌던 것이 문제였습니다. 배율 표에는 유효 기간 칸이 분명히 있었는데 그 칸을 계산에 넣지 않았습니다.
유효 기간을 빠뜨리기 쉬운 이유가 있습니다. 캐시를 쓰다 보면 TTL은 저절로 유지되는 값처럼 느껴집니다. 히트가 날 때마다 추가 비용 없이 수명이 갱신되기 때문입니다. 그래서 자주 도는 워크로드에서는 5분 캐시가 반영구적으로 살아 있는 것처럼 보이고, TTL이라는 개념이 의식에서 사라집니다.
문제는 갱신이 히트를 전제로 한다는 점입니다. 한 번이라도 창을 넘기면 갱신할 대상 자체가 없어집니다. 자주 도는 구간에서는 신경 쓸 일이 없던 값이, 간격이 벌어진 구간에서는 유일한 변수가 됩니다.
슬롯 간격을 실제로 재 봤습니다
오늘 세 슬롯의 실행 시각입니다.
from datetime import datetime
# 2026-09-18 실제 실행 시각 (KST). 예약 작업 목록의 lastRunAt 을 KST 로 환산한 값입니다
t = ["2026-09-18 08:08:39", "2026-09-18 13:05:10", "2026-09-18 17:15:20"]
ts = [datetime.fromisoformat(x) for x in t]
for i in (1, 2):
d = (ts[i] - ts[i-1]).total_seconds()
print(f"간격 {int(d):,}초 · 5분의 {d/300:.1f}배 · 1시간의 {d/3600:.2f}배")
# 간격 17,791초 · 5분의 59.3배 · 1시간의 4.94배
# 간격 15,010초 · 5분의 50.0배 · 1시간의 4.17배
5분 TTL의 59.3배, 1시간 TTL로 늘려도 4.94배입니다. 슬롯과 슬롯 사이에 살아남는 캐시는 없습니다. 하루 세 번 같은 문서를 읽지만, 캐시 입장에서 그것은 서로 남남인 세 번입니다.
히트가 0회면 쓰기 배율만 남습니다
이 구간의 비용을 계산하면 방향이 뒤집힙니다. 슬롯이 매 실행 읽는 공유 문서 세 개는 축로테이션 9,383토큰, 원고문체 8,981토큰, 발행절차 29,438토큰으로 합계 47,801토큰이었습니다. 한글 토큰 수를 실측했던 계수 중 o200k_base 값으로 환산한 값입니다.
여기에 보정이 하나 필요합니다. Opus 5는 새 토크나이저를 쓰는 세대라 같은 텍스트에서 토큰이 더 많이 나옵니다. 공식 문서가 밝힌 증가폭 약 30%를 넣으면 62,141토큰입니다. 이 값에 Opus 5 입력가 $5/MTok을 대입합니다.
| 시나리오 | 3회 합계 | 미캐시 대비 |
|---|---|---|
| 캐시 안 씀 | $0.9321 | 기준 |
| 5분 캐시 · 전부 미스 | $1.1651 | +25.0% |
| 1시간 캐시 · 전부 미스 | $1.8642 | +100.0% |
| 5분 캐시 · 1쓰기 + 2히트 | $0.4505 | −51.7% |
맨 아래 줄이 제가 기대했던 값이고, 실제로 일어나는 것은 두 번째 줄입니다. 절반을 아끼려다 4분의 1을 더 내는 자리입니다.
하루 23센트라 액수는 작습니다. 다만 이 계산은 공유 문서 세 개만 센 것이고, 실제 전송되는 프리픽스에는 대화 이력과 도구 정의가 얹힙니다. 비율은 그대로이고 분모만 커집니다. 30일이면 $6.99이고요.
그리고 이 손실은 조용합니다. 오류도 경고도 없고, 응답 품질도 그대로입니다. 켜 두었다는 사실만 기억에 남고 결과는 청구서에만 남습니다. 절감 목적으로 켠 기능이 반대로 도는데 아무 신호가 없는 것이 이 구조에서 제일 나쁜 점입니다.
수명은 요청이 시작될 때부터 깎입니다
TTL을 창 안에 두려고 할 때 한 번 더 걸리는 곳이 있습니다. 수명은 캐시를 쓰거나 읽는 요청이 시작되는 시점부터 재고, 응답을 만드는 시간도 그 수명에서 빠져나갑니다.
응답 스트리밍에 4분이 걸렸다면 5분 창에서 1분 남짓만 남습니다. 긴 추론이나 도구 결과를 여러 개 물고 오는 턴에서는 이 차이가 작지 않습니다. "5분 안에 다음 요청을 보내면 된다"가 아니라 "직전 요청이 시작된 뒤 5분 안"이라고 읽어야 맞습니다.
간격이 3~4분대로 붙어 있는 워크로드라면 이 한 줄 때문에 히트율이 눈에 띄게 떨어질 수 있습니다. 그런 구간에서는 1시간 TTL로 올려 두는 편이 안전하고, 대신 재사용이 3회 이상이라는 조건을 먼저 확인해야 합니다.
정말 히트가 났는지는 응답이 알려 줍니다
배율을 짐작으로 판단할 필요가 없습니다. 응답의 usage에 캐시 관련 필드가 그대로 찍힙니다.
# 캐시가 실제로 걸렸는지 판정하는 세 값
# cache_creation_input_tokens : 이번 요청에서 새로 쓴 토큰 (쓰기 배율로 과금)
# cache_read_input_tokens : 캐시에서 읽은 토큰 (0.1배로 과금)
# input_tokens : 캐시를 타지 않은 나머지
u = response.usage
if u.cache_read_input_tokens == 0 and u.cache_creation_input_tokens > 0:
print("매번 새로 쓰고만 있습니다 — 쓰기 배율만 물고 있는 상태입니다")
둘 다 0이면 캐싱이 아예 안 걸린 것입니다. 이 경우 오류가 나지 않는다는 점을 문서가 따로 적어 두었습니다. 최소 캐시 가능 토큰에 미달하면 캐싱 요청은 조용히 무시되고 요청은 정상 처리됩니다.
캐시가 깨지는 자리는 맨 위에 있습니다
간격을 맞췄다고 끝이 아닙니다. 캐시는 tools → system → messages 계층을 따르고, 위쪽이 바뀌면 아래가 전부 무효가 됩니다.
| 바뀐 것 | tools | system | messages |
|---|---|---|---|
| 도구 정의(이름·설명·파라미터) | 무효 | 무효 | 무효 |
| 웹 검색 · 인용 켜고 끄기 | 유지 | 무효 | 무효 |
tool_choice 변경 |
유지 | 유지 | 무효 |
| 이미지 추가·제거 | 유지 | 유지 | 무효 |
도구 목록이 흔들리는 환경이 제일 불리합니다
맨 윗줄이 이 파이프라인에 그대로 해당합니다. 오늘 실행에서도 외부 MCP 서버 여섯 개가 DNS 오류로 연결에 실패했습니다. 연결되는 날과 안 되는 날의 도구 목록이 다르면 tools 블록이 달라지고, 그러면 그날은 아래 전부가 새로 쓰기입니다.
여기서 한 가지가 분명해집니다. 도구를 많이 붙일수록 캐싱의 이득도 커지지만, 도구 목록이 불안정할수록 그 이득이 통째로 날아갑니다. 붙인 개수보다 목록이 고정되어 있는지가 먼저입니다.
같은 이유로 도구 설명 문구를 다듬는 작업도 공짜가 아닙니다. 이름이나 파라미터뿐 아니라 설명 한 줄만 고쳐도 tools 해시가 바뀌어 그 뒤 전부가 무효입니다. 프롬프트를 자주 손보는 초기에는 캐싱이 기대만큼 일하지 않을 수 있습니다.
직렬화 순서 같은 것도 캐시를 깹니다
캐시 히트는 표시한 블록까지의 텍스트와 이미지가 100% 동일할 때만 납니다. 눈에 안 보이는 차이도 차이로 셉니다.
문서가 콕 집어 경고하는 사례가 tool_use 블록의 키 순서입니다. 일부 언어는 객체를 JSON으로 만들 때 키 순서를 무작위로 섞는데, 그러면 사람이 보기에 같은 요청이 매번 다른 프리픽스가 됩니다. 캐싱을 켰는데 히트가 0에 가깝고 간격도 짧다면 이쪽을 의심할 만합니다.
브레이크포인트는 최대 4개까지 둘 수 있고, 각 지점마다 뒤로 20블록까지만 되짚어 봅니다. 대화가 길어져 마지막 쓰기 지점이 20블록 밖으로 밀리면 그때부터는 히트가 안 납니다. 자동 캐싱도 같은 4개 슬롯 중 하나를 쓰므로, 명시적 브레이크포인트를 4개 다 채워 두면 자동 캐싱 요청은 400으로 거절됩니다.
도구 정의만으로도 적지 않게 나갑니다
공식 문서가 도구별 토큰 수를 표로 공개해 두었습니다. Opus 5 기준이고, 캐시 열은 쓰기 1회에 히트 49회로 계산한 값입니다.
| 항목 | 토큰 | 50회 왕복 미캐시 | 50회 왕복 캐시 |
|---|---|---|---|
| 도구 사용 시스템 프롬프트(any·tool) | 406 | $0.1015 | $0.0125 |
| bash 도구 | 325 | $0.0813 | $0.0100 |
| computer 툴셋 기본 | 약 4,520 | $1.1300 | $0.1390 |
| browser 툴셋 기본 | 약 6,610 | $1.6525 | $0.2033 |
툴셋 두 값은 개별 도구 정의에 도구 사용 시스템 프롬프트까지 포함한 수치입니다. 둘을 같이 붙일 때 단순히 더하면 시스템 프롬프트를 두 번 세게 되므로, 정확한 합계는 응답의 usage나 토큰 계산 엔드포인트로 확인하는 편이 맞습니다.
절감률 자체는 토큰 수와 무관합니다. 쓰기 1회에 히트 49회면 배율 합이 6.15이고, 50 대비 87.7% 감소입니다. 이쪽은 한 세션 안에서 초 단위로 반복되니 TTL 문제가 없습니다.
토큰 수를 잘못 세면 계산 전체가 어긋납니다
지금까지의 계산은 전부 토큰 수를 분모로 씁니다. 그 값이 틀리면 손익분기도 문턱 판정도 같이 틀립니다.
최소 캐시 가능 토큰은 모델마다 8배 차이가 납니다
같은 프롬프트라도 모델에 따라 캐싱이 걸리기도 하고 안 걸리기도 합니다.
| 모델 | 최소 캐시 가능 토큰 |
|---|---|
| Opus 5 | 512 |
| Opus 4.8 · Sonnet 5 | 1,024 |
| Opus 4.7 | 2,048 |
| Opus 4.5 · 4.6 | 4,096 |
| Haiku 4.5 | 4,096 |
Haiku 4.5가 4,096으로 가장 높습니다. 값싼 모델에 짧은 시스템 프롬프트를 물려 두고 캐싱을 켰다면 미달로 조용히 빠졌을 가능성이 있습니다. 앞서 적은 대로 오류가 안 나므로 usage 두 필드를 직접 보는 수밖에 없습니다.
세대가 올라갈수록 문턱이 내려가는 흐름이 보입니다. 다만 이것을 가격과 묶어 읽으면 틀립니다. Opus 4.5와 4.6은 Haiku 4.5보다 다섯 배 비싼데 문턱은 4,096으로 같습니다. 가격이 아니라 출시 시점에 가까운 경향이고, 그마저도 모델을 하나하나 확인하는 편이 안전합니다.
제 공유 문서는 가장 작은 원고문체가 8,981토큰이라 표의 모든 모델에서 문턱을 통과합니다. 문턱이 문제인 구간은 시스템 프롬프트가 몇 문단짜리인 소형 서비스 쪽입니다.
새 토크나이저가 30%를 더 셉니다
앞 절에서 47,801토큰에 30%를 얹어 62,141토큰으로 계산한 근거가 여기 있습니다. Claude 4.7 이상 모델은 새 토크나이저를 쓰고, 같은 텍스트에서 약 30% 더 많은 토큰이 나옵니다.
다만 문서는 "정확한 증가폭은 내용과 작업 형태에 따라 다르다"는 단서를 같이 답니다. 30%는 대푯값이지 고정 계수가 아닙니다. 예산을 잡을 때는 이 값으로 잡되, 실제 청구서와 어긋나면 토크나이저 쪽부터 의심하는 순서가 맞습니다.
주의할 것은 이 30%가 캐시 문턱에도 똑같이 적용된다는 점입니다. 문턱을 아슬아슬하게 넘던 프롬프트는 모델을 올리면 오히려 여유가 생기고, 반대로 예산은 그만큼 더 나갑니다. 두 방향이 같이 움직이므로 한쪽만 보고 판단하면 안 됩니다.
판단 표
| 방법 | 도입 난이도 | 유지보수 비용 | 팀 학습곡선 |
|---|---|---|---|
자동 캐싱(최상위 cache_control 1개) |
낮음 — 필드 하나 | 낮음 | 낮음. 다만 마지막 블록이 매번 바뀌면 무용 |
| 명시적 브레이크포인트(최대 4개) | 중간 — 블록 구조 설계 필요 | 중간 — 프롬프트 개편 때마다 재검토 | 중간. 무효화 계층을 알아야 함 |
| 1시간 TTL 전환 | 낮음 — ttl 값만 변경 |
낮음 | 낮음. 단 3회 이상 재사용이 전제 |
| 캐싱 안 씀 | 없음 | 없음 | 없음. TTL을 못 맞추는 배치성 작업의 기본값 |
제가 이번 주에 캐싱을 켜지 않기로 한 이유
세 슬롯에는 안 켜기로 했고요, 대신 한 슬롯 실행 안에서 도는 왕복 쪽만 보기로 했습니다. 거기는 간격이 초 단위라 TTL이 문제가 되지 않거든요.
슬롯을 서로 붙여서 TTL 안에 넣는 방법도 생각해 봤는데요, 그건 캐시를 아끼려고 발행 시간표를 바꾸는 일이라 앞뒤가 뒤집힙니다. 08시·13시·17시라는 간격은 읽는 사람을 보고 정한 값이고, 하루 23센트 때문에 건드릴 값은 아닙니다만 판단은 각자 다를 수 있습니다.
정리하면 제가 틀렸던 지점은 하나입니다. 재사용 횟수는 셌는데 재사용 간격을 안 셌습니다. 손익분기 N=2는 맞는 값이지만, 그 N은 TTL 창 안에서 세야 하는 N이었습니다. 창 밖에서 센 N은 아무리 커도 히트로 이어지지 않습니다. 예약 작업처럼 시간을 벌려 놓은 구조에서는 슬롯 간격 자체가 설계 변수라는 것을 한 번 더 확인한 셈입니다.
혹시 지금 캐싱을 켜 두셨다면, 켜져 있다는 사실보다 히트가 나고 있는지가 먼저입니다. 아래 네 줄이 판정 순서입니다.
# 1) 같은 프리픽스가 재사용되는 간격을 먼저 잰다. 이것이 TTL(300초/3600초)보다 작아야 한다
# 로그가 없다면 예약 작업의 마지막 실행 시각 차이로 대신 재도 된다
# 2) 응답 usage 의 cache_read_input_tokens 를 며칠치 모아 0인지 본다
# 계속 0이면 켜 둔 만큼 쓰기 배율을 더 내고 있는 상태다
# 3) 둘 다 0이면 최소 캐시 가능 토큰 미달을 의심한다 (Haiku 4.5 는 4,096)
# 4) 도구 목록이 실행마다 달라지는지 확인한다. 달라지면 tools 계층부터 전부 무효다
grep -c "cache_read_input_tokens\":0" ~/logs/api-*.jsonl
네 줄 중 하나라도 걸리면 지금 켜 둔 캐싱은 절감이 아니라 할증입니다. 반대로 네 줄이 전부 통과하고 TTL 창 안 재사용이 2회 이상이면 켜 두는 쪽이 맞고요. 금액은 환경마다 다르니 이 판정 순서만 들고 계셔도 충분합니다.
댓글
댓글 쓰기