2026년 8월 30일 일요일

LLM 서빙 캐싱 ⑨ — 캐시 수명주기 운영: 워밍, 콜드 캐시, 오토스케일링

히트율은 설계 시점의 속성이 아니다. 파드가 늘어날 때, 모델을 교체할 때, 스팟 노드가 회수될 때, 트래픽이 TTL보다 뜸해질 때마다 무너진다. API 사용자에게는 "4분 30초마다 핑을 보내 5분 캐시를 살려둘까"가 곧 청구서 결정이고, 자체 서빙에서는 오토스케일링이 캐시 지역성을 깬다. 이 글은 캐시가 죽는 순간의 비용을 계산한다.

캐시는 쓰는 순간이 아니라 죽는 순간에 돈이 샌다

만료 모델이 벤더마다 다르다. Anthropic은 5분/1시간 TTL이고 읽힐 때마다 무료로 갱신되며 수명은 요청 시작 시점부터다. OpenAI(GPT-5.6+)는 마지막 사용 후 30분 슬라이딩, 구모델은 prompt_cache_retention: "24h"가 추가 요금 없이 제공된다 — 워머가 필요 없다. Gemini 명시적 캐시는 시간당 저장료(2.5 Pro $4.50, Flash·3.x $1.00 per M토큰·시간)가 붙는다. 만료 뒤 첫 요청은 쓰기 할증(×1.25 또는 ×2)을 다시 낸다.

keep-alive 손익분기 — Sonnet 5로 직접 계산

  • 단가(프리픽스 1M 토큰당): 읽기 $0.20, 5분 쓰기 $2.50, 1시간 쓰기 $4.00. 5분 워머(max_tokens: 0, 공식 지원) 유지비 = 시간당 읽기 12회 = $2.40/시간. 미스 1회 추가 비용 = 쓰기 − 읽기 = $2.30. 1시간 캐시 프리미엄 = $1.50/쓰기.
  • 결론 1: 5분 워머는 다음 요청이 ~57분 안에 확실할 때만 이득이고, 1시간 공백을 워머($2.40)로 메우는 것보다 1시간 TTL($1.50)이 싸다. 요청이 시간당 0.55건만 넘어도 1시간 TTL이 5분을 이긴다. 10분 간격 트래픽 예: 5분 캐시 $8.37/시간, 5분+워머 $1.46~2.40, 1시간 캐시 $0.06.
  • 결론 2: 프롬프트 하나의 keep-alive는 동전 단위다(10K 프리픽스면 야간 15시간 유지 vs 재작성 차이 $0.01). 진짜 돈은 요청당 미스율 × 요청 수 — 팬아웃과 롤아웃 — 에서 샌다. 아침 프리워밍은 첫 사용자의 쓰기를 앞당길 뿐 비용 +0, TTFT만 이득.
  • Gemini: 명시적 캐시는 시간당 히트 4건 이상일 때만 회수되고, 2.5 Pro 100K를 야간 15시간 유지하면 재생성의 54배 — 퇴근 시 삭제, 출근 시 재생성(expireTime).

팬아웃과 롤아웃 — 캐시가 한꺼번에 비는 두 순간

  • 팬아웃: 캐시는 "첫 응답이 시작된 뒤"에 생긴다. 10K 프리픽스를 워커 50개가 동시에 콜드로 치면 50 × $0.025 = $1.25, 첫 요청의 first-byte를 기다린 뒤 49개를 보내면 $0.12 — 1/10이다.
  • 스케일아웃: 라운드로빈이면 N→N+1 직후 클러스터 히트율 ≈ 기존 × N/(N+1)(4→5대면 즉시 −20%p). 사용자별 멀티턴이 대부분이면 옮겨진 대화마다 전체 prefill 1회 — "동기화된 재계산 폭풍"이고 롤링 업데이트는 이를 레플리카 수만큼 반복한다. llm-d의 sticky-until-saturated는 캐시 토큰 80% 이상 엔드포인트에 붙이되 미캐시 in-flight 토큰이 임계를 넘을 때만 새 레플리카를 열어 기존 히트율을 보존하고, P2P KV 풀은 48K 프리픽스 재계산 1,988ms를 235ms로 줄였다.
  • 국내 사례: 토스증권(2026-08)은 배포 직후 프리픽스 캐시 히트율 0% — 설정 실수가 아니라 reasoning 모델 특성상 기본으로 꺼져 있었다. 켜니 20초 가까이 걸리던 TTFT가 1/10, 히트율 90%+. 같은 글의 다른 교훈: KV 사용률 1% 미만인데 처리량이 포화 → 동시성 한도만 올려 4배.
  • 롤아웃 = 전체 무효화: 토크나이저·챗 템플릿·모델 버전이 바뀌면 L3 스토어의 KV까지 전부 무효(Claude 4.7+ 토크나이저도 토큰 ~30% 증가). 모델 업데이트는 업무시간 밖에, 카나리 1대를 readiness probe에서 핫 시스템 프롬프트 N개로 한 바퀴 데운 뒤 전환.

게이트웨이가 안 해주는 것, 스케일링 신호, 스팟

동일 요청이 동시에 N건 들어올 때의 in-flight 병합(singleflight)은 Cloudflare가 문서로 명시하듯 아무도 안 해준다("동시에 온 두 번째 요청은 첫 번째가 캐시되기 전일 수 있다") — LiteLLM·Portkey·Helicone·Kong 전부 응답 캐시일 뿐이다. temperature 0 + body 해시로 "동일"을 정의하고 앱에서 Go singleflight나 Redis SET NX로 직접 구현한다. 스케일링 신호는 GKE 권고대로 큐 깊이(3~5) > 배치 크기 > GPU 지표 — vllm:kv_cache_usage_perc는 메모리 압력이지 과부하가 아니다. KEDA 기본 cooldown 300초는 LLM 파드 기동보다 짧을 수 있으니 기동 시간 이상으로. 스팟은 GCP 최대 91% 할인이지만 통지 0~120초·유예 30초, AWS 2분이라 80GB의 KV를 내보낼 수 없다 — HiCache/LMCache의 L3 write-through가 전제이고, 스팟은 배치·오프피크 prefill 풀에, 실시간 디코드는 온디맨드에.

한국 시간대의 트래픽 셰이핑과 고정 GPU

KST 09~18시 형태의 트래픽이면: Anthropic 1시간 TTL 기본(점심 공백 통과, 아침 프리워밍 1회), OpenAI는 24h, Gemini는 09시 생성·18시 만료. DeepSeek의 피크(UTC 01~04·06~10시)는 정확히 KST 10~13시, 15~19시 — 한국 업무시간이라 오프피크 50%를 받으려면 비실시간 작업을 13~15시와 19시 이후로 옮긴다. Batch API는 시간대 무관 50%이고 Anthropic은 캐시 할인과 중첩된다(배치 내 히트율 30~98%, 1시간 TTL 권장). 그리고 ⑪편에서 다룰 KT·NCP 고정 할당 GPU는 scale-in이 없어 "항상 따뜻하지만 야간에 논다" — 여기서는 keep-alive 문제가 사라지는 대신 야간 15시간을 채우는 배치(임베딩 재생성·평가·요약 백로그)가 곧 절감이다. 다음 글은 프리픽스를 캐시하는 대신 아예 안 보내는 선택, 파인튜닝과의 손익 비교다.

— LLM 서빙 캐싱 시리즈 ⑨ / 다음 글: 캐시 vs 파인튜닝 vs 프롬프트 압축 — 프리픽스를 안 보내는 선택

댓글 없음:

댓글 쓰기

국정원의 댓글 공작을 지탄합니다.

RAG 종류 총정리 ⑬ (완결) — 한국어 조건과 결정 트리

열두 편을 한 장으로 접는다. 먼저 한국어로 서비스할 때만 적용되는 조건을 모으고, 그다음 "우리는 무엇부터 하나"를 결정 트리로 정리한다. 한국어 RAG의 다섯 가지 조건 임베딩 기본값을 의심하되, 갈아타는 이득은 제한적이...