10. prefix caching
핵심 질문
- 요청들이 앞부분을 공유할 때, 무엇을 재사용할 수 있는가 — 정확히 어디까지인가?
- prefix 재사용은 어떤 안전 가정을 은근히 깔고 있는가?
목표
- exact prefix hit가 재사용하는 것이 "어떤 prefill까지인가"를 정확히 짚는다.
- 테넌트(tenant) 격리를 가정하지 않는 관점을 세운다.
여정에서의 위치
09장에서 KV가 블록 단위로 관리되면 여러 요청이 같은 물리 블록을 공유할 수 있다고 했습니다. prefix caching은 그 가능성을 실현합니다: 여러 요청의 프롬프트 앞부분(prefix)이 동일하면, 그 부분의 KV를 다시 계산하지 않고 재사용합니다.
일상 비유: 여러 손님이 같은 애피타이저로 시작한다면, 그 애피타이저는 한 번만 만들어 나눠 낼 수 있습니다. 단, 메인 요리부터 갈리는 순간 각자 따로 만들어야 합니다.
flowchart LR
R1[요청1: 시스템프롬프트 + 질문A]:::req
R2[요청2: 시스템프롬프트 + 질문B]:::req
SP[공유 prefix<br/>시스템프롬프트 KV]:::mem
R1 -->|앞부분 동일| SP
R2 -->|앞부분 동일| SP
SP --> P1[질문A만 새로 prefill]:::comp
SP --> P2[질문B만 새로 prefill]:::comp
classDef req fill:#fff3bf,stroke:#f59f00,color:#000;
classDef mem fill:#e5dbff,stroke:#7048e8,color:#000;
classDef comp fill:#d0ebff,stroke:#1971c2,color:#000;
RAG나 공통 시스템 프롬프트처럼 앞부분이 반복되는 워크로드에서 prefill 비용을 크게 아낄 수 있어, TTFT(14장)를 낮출 수 있습니다.
정확히 무엇을 재사용하나: "어떤 prefill까지"
여기가 이 장에서 가장 중요한 정밀함입니다. exact prefix hit(정확 접두 일치)가 재사용하는 것은 처음부터 "완전히 동일한 토큰 열"이 이어지는 지점까지의 prefill 결과(KV)입니다.
- 재사용 범위는 첫 번째로 토큰이 달라지는 자리에서 끝납니다. 그 이후는 새로 prefill해야 합니다.
- "비슷한" 프롬프트가 아니라 토큰 단위로 정확히 같은 접두여야 합니다. 한 토큰만 달라도 그 지점부터 hit가 끊깁니다.
- 대개 블록 단위로 매칭되므로(09장), 재사용은 블록 경계까지 정렬되는 방식으로 이뤄집니다.
⚠️ 흔한 실수
흔한 오해 1: "내용이 비슷하면 재사용된다"아닙니다. 의미가 비슷해도 토큰 열이 다르면 exact prefix hit는 일어나지 않습니다. prefix caching은 의미 캐시가 아니라 접두 토큰 일치 캐시입니다.
⚠️ 흔한 실수
흔한 오해 2: "prefill 전체가 공짜가 된다"아닙니다. 공유되는 것은 동일 접두 부분의 prefill뿐입니다. 요청 고유 부분(질문·문서)은 여전히 새로 계산합니다.
🔒 테넌트 격리를 가정하지 마라
prefix caching은 "서로 다른 요청이 KV를 공유한다"는 성질을 갖습니다. 이 성질은 편리하지만, 누구의 요청끼리 공유되는가를 반드시 물어야 합니다.
- 캐시가 여러 사용자·테넌트에 걸쳐 공유되면, 한 사용자의 프롬프트 앞부분이 다른 사용자의 요청 처리에 영향을 줄 수 있는 경로가 생깁니다. 예컨대 캐시 히트 여부가 응답 시간(타이밍)에 드러나 어떤 프롬프트가 앞서 존재했는지 추론하는 부채널(side-channel) 가능성이 논의됩니다.
- 따라서 "prefix caching = 항상 안전한 최적화"라고 가정하지 않습니다. 격리 경계(사용자별·테넌트별 캐시 분리 여부)는 설계 선택이며, 자료가 그것을 명시하지 않으면
unknown으로 두어야 합니다.
🔬 증거 읽기 (주장 유형·조건)
- "prefix caching이 RAG에서 TTFT를 크게 낮춘다"는 inferred/measured로, 앞부분이 실제로 반복되는 워크로드라는 조건에서만 참입니다. 접두가 매번 다른 워크로드에선 이득이 거의 없습니다.
- "prefix caching은 안전하다"는 주장은 테넌트 격리 가정을 은근히 깔고 있습니다. 그 가정이 명시·검증됐는지 확인하기 전에는 받아들이지 마세요. 이는 owner의 기능 설명(vendor-reported)이 보안 보증과 다른 대표적 사례입니다.
⚖️ 절충
prefix caching은 반복 접두 워크로드에서 prefill↓·TTFT↓를 얻지만, 캐시 관리 복잡도·메모리 점유·(교차 테넌트 시) 격리 리스크를 더합니다. 이득의 크기는 전적으로 워크로드의 접두 반복률에 달려 있습니다.
여정에 다시 위치시키기
지금까지 3부(07~10장)는 "여정의 스케줄링·메모리 구간"에서 병목을 하나씩 다뤘습니다.
- 07 배칭: 가중치 로드 비용을 나눠 쓰되, static의 낭비.
- 08 continuous batching: 매 반복 재구성으로 낭비↓, 단 선점 비용.
- 09 PagedAttention: KV 단편화↓, 단 블록 관리 비용.
- 10 prefix caching: 접두 prefill 재사용, 단 워크로드 의존·격리 가정.
공통 교훈: 각 최적화는 특정 조건에서 특정 병목을 옮길 뿐, 무료도 무조건도 아니다. 이 태도가 4부(양자화·speculative)와 5부(지표·벤치마크 비판)로 이어집니다.
📌 핵심
- prefix caching은 정확히 동일한 접두 토큰 열의 prefill 결과(KV)를 재사용한다 — 첫 불일치 지점에서 끝난다.
- "비슷함"이 아니라 토큰 단위 정확 일치이며, 요청 고유 부분은 여전히 새로 계산.
- 이득은 접두 반복 워크로드(RAG·공통 시스템 프롬프트)에서만 크다.
- 테넌트 격리를 가정하지 말 것 — 교차 사용자 공유 시 부채널 등 리스크가 있고, 격리는 명시돼야 할 설계 선택.
🔎 이 장의 '지지하지 않는 결론'
- "prefix caching은 항상 이득"이라고 말할 수 없습니다 — 접두가 반복되지 않으면 이득이 없습니다.
- "prefix caching은 안전하다"를 단정할 수 없습니다 — 테넌트 격리 여부가 확인돼야 합니다.
✍️ 확인 문제
- exact prefix hit가 재사용하는 범위가 "첫 불일치 지점까지"인 이유를, autoregressive KV의 성질로 설명하세요.
- 의미가 비슷한 두 프롬프트가 prefix hit를 못 내는 이유는?
- (조건 유형) "prefix caching은 빠르고 안전하다"는 문장에서, '빠르다'와 '안전하다' 각각이 성립하려면 어떤 조건이 필요합니까?
다음 묶음(4부): 11 · 양자화의 절충 → 12 · speculative decoding과 MTP. 정밀도와 속도의 거래로.