메모리를 삼키는 주범 — KV Cache

← 전체 목차 · 이전: "다음 단어 예측"만으로는 부족하다 — LLM 추론 전 과정 · 다음: MoE는 일부 전문가만 활성화하는데 왜 메모리를 많이 먹나

긴 대화에서 GPU 메모리가 폭증하는 주범은 모델 가중치가 아니다. 가중치는 고정불변인 십몇 GB이고, 진짜로 팽창하는 것은 KV Cache다.

대상행동
모델 가중치고정불변, 십몇 GB
KV Cache지속 팽창, 대화가 길어질수록

체감 규모: 가중치는 십몇 GB인데 긴 대화에서 메모리가 수십 GB, 심지어 100 GB 이상까지 오른다.

왜 캐시가 필요한가

  • 대규모 모델은 한 번에 문단 전체를 쓰지 않고 token을 하나씩 밖으로 생성한다.
  • 새 token을 생성할 때마다 앞의 전체 문맥을 되돌아보며 다음에 무엇이 올지 판단한다.
  • 매 단계마다 모든 과거 token을 다시 계산하면 긴 텍스트일수록 점점 느려진다(복잡도가 길이의 제곱으로 증가).

KV Cache가 하는 일

캐시 없음:  t단계 → token 1..t의 K/V를 다시 계산 → 주의력 → 출력      (반복 재계산)
캐시 있음:  t단계 → token t의 Q/K/V만 계산 → 캐싱된 K/V와 주의력 → 출력
                    └─ 새 K/V를 캐시에 추가
  • 저장하는 것은 과거 token들이 이미 계산해 둔 Key와 Value다.
  • 수익: 추론이 반복 재계산에서 증분 계산으로 바뀐다.
  • 대가: 메모리로 연산력을 산다 — 이 문서의 가장 핵심적인 규정이다.

왜 K와 V만 캐싱하고 Q는 캐싱하지 않는가

벡터생명주기캐싱할 가치
K, V과거 token의 K/V는 이후에도 반복적으로 조회된다있음, 반드시 캐싱
Q이번 한 번의 조회에만 봉사하고 쓰고 나면 실효없음, 저장해도 메모리 낭비

Query의 생명주기는 현재 한 번의 조회뿐이다. 캐싱해 두면 재사용 가치 없이 메모리만 잡아먹는다.

메모리가 이렇게 빨리 느는 이유: 세 인자 분해

인자설명
모델 층수층이 많을수록, 각 층마다 저장해야 한다 (층별 독립 저장)
컨텍스트 / 대화 길이대화가 길수록, 새 token마다 계속 추가된다
모델 규모규모가 클수록 주의력 헤드 수와 차원도 커질 수 있다

KV Cache ≈ 층수 × 시퀀스 길이 × 헤드 수 × 헤드 차원 × 2(K와 V) × 정밀도 바이트 수.

결론: 롱컨텍스트 시나리오에서 KV Cache는 가중치보다도 메모리를 더 먹을 수 있다.

다섯 가지 엔지니어링 최적화

방안작용점
PagedAttention메모리 단편화 감소
FlashAttention데이터 이동량 감소
KV 양자화캐시 압축
접두사 캐시(Prefix Cache)공통 접두사 재사용 / 중복 오버헤드 통제
슬라이딩 윈도우컨텍스트 길이 통제

한 줄 답변

KV Cache는 추론 단계의 단기 기억이다. 생성을 빠르게 하지만, 메모리 압박을 모델 가중치에서 컨텍스트 길이로 이전시킨다.

핵심 통찰

  1. KV Cache는 전형적인 "시간을 공간으로 바꾸는" 조작이다 — 메모리를 희생해 연산력을 얻고, O(n²)의 반복 계산을 O(n)의 증분 계산으로 평탄화한다. "캐시"를 언급하는 모든 최적화는 첫 문장에서 무엇을 바꾸고 무엇을 지불하는지를 분명히 해야 한다.
  2. 어떤 중간 결과가 캐싱할 가치가 있는지는 재사용 횟수만 보면 된다 — K/V는 이후의 모든 token에 반복 조회된다(재사용 횟수 = 남은 생성 길이). Q는 한 번만 쓰인다. 이 판정 기준은 어떤 시스템의 캐시 설계에도 그대로 이식된다.
  3. 메모리 장부는 "정적"과 "동적" 두 권으로 나눠야 한다 — 가중치는 정적이고 예측 가능하며, KV Cache는 동적이고 요청 길이와 동시성에 따라 증가한다. 용량 계획에서 가중치만 계산하면 긴 대화에서 반드시 뒤집힌다. "모델은 십몇 GB뿐인데 메모리가 터진다"의 근본 원인이다.
  4. KV Cache가 롱컨텍스트의 진짜 비용 센터다 — 모델이 얼마나 긴 컨텍스트를 지원한다고 표방하는 것과, 그 길이의 KV Cache를 메모리에 실제로 담을 수 있는지는 별개다. 윈도우 길이의 상업적 가격 책정이 여기서 결정되는 경우가 많다.
  5. 최적화 수단은 "작용 차원"으로 분류해 기억할 것 — 단편화 감소(PagedAttention), 이동량 감소(FlashAttention), 표현 압축(KV 양자화), 시퀀스 단축(슬라이딩 윈도우), 중복 회피(접두사 캐시). 이 다섯 개의 동사만 기억하면 방안 목록을 스스로 도출할 수 있다.
  6. QKV의 책임 차이가 추론 단계에서 그대로 엔지니어링 결론으로 환전된다 — 학습 시점에는 "Q가 찾고, K가 찾히고, V가 내용을 준다"가 순수 이론처럼 보이지만, 추론 단계에서는 "K/V만 캐싱한다"는 강제 설계가 된다. 이론과 엔지니어링이 여기서 맞물린다.

엔지니어링 실전 Tips

  • 용량 계획 공식을 종이에 적어둘 것: 메모리 ≈ 가중치 + 활성화 + 2 × 층수 × 시퀀스 길이 × KV 헤드 수 × 헤드 차원 × 바이트 수 × 동시성. 동시성이 자주 누락되며, 프로덕션 OOM의 고빈도 원인이다.
  • 접두사 캐시는 다중 턴 대화와 고정 시스템 프롬프트에서 수익이 가장 크다: 같은 접두사가 수천~수만 요청 사이에서 재사용되면 중복 prefill 오버헤드를 그대로 잘라낼 수 있다.
  • KV 양자화(FP8 / INT8)는 가성비가 가장 높은 한 수: KV 메모리를 거의 선형으로 압축하며 정밀도 손실은 대개 수용 가능하다. 모델 아키텍처를 바꾸는 것보다 훨씬 쉽다.
  • PagedAttention이 해결하는 것은 단편화이지 총량이 아니다: 메모리를 "페이지 단위"로 할당·재사용하게 해 동시성을 높인다. 단일 요청의 KV 부피를 낮춰주리라 기대하지 말 것.
  • 슬라이딩 윈도우는 손실이 있는 방안이다: 컨텍스트 길이를 통제한다는 것은 먼 과거를 능동적으로 버린다는 뜻이므로, 작업이 장거리 정보에 의존하는지 평가한 뒤 켤 것.
  • 첫 글자 지연(TTFT)은 KV Cache와 강하게 연결된다: prefill 단계에서 모든 과거의 K/V를 한 번에 계산해야 하므로 긴 프롬프트는 첫 글자 지연을 직접 늘린다. "프롬프트를 너무 길게 쓰지 말라"의 엔지니어링적 근거 중 하나다(문서 08 참조).
  • 더 파고들 방향: MQA / GQA(KV 헤드 수를 아키텍처 층위에서 직접 줄인다), MLA 같은 저랭크 압축 노선, Prefill과 Decode의 분리 배포(PD 분리)가 KV Cache 전송에 미치는 영향, KV Cache의 CPU/NVMe 오프로딩과 요청 간 공유.