LLM을 실행할 때 모델의 크기만 확인하고 필요한 메모리를 계산하면 실제 실행 환경에서는 예상과 다른 결과가 나온다.
모델의 가중치는 로딩이 끝나면 크게 변하지 않지만, 추론 과정에서 사용하는 KV Cache는 Context가 늘어날수록 계속 증가하기 때문이다.
그 중심에 있는 것이 LLM KV Cache다.
LLM KV Cache는 LLM의 토큰 생성 속도를 높이기 위해 반드시 필요한 구조이면서, 동시에 추론 과정에서 메모리를 계속 사용하는 대표적인 영역이다.

LLM KV Cache, 왜 이름이 KV Cache인가
Transformer의 Attention은 입력된 토큰을 Query(Q), Key(K), Value(V)라는 세 가지 형태의 데이터로 변환해 처리한다.
쉽게 말하면 Query는 현재 필요한 정보를 찾기 위한 질의이고, Key는 어떤 정보가 관련되어 있는지 판단하기 위한 기준, Value는 실제로 전달할 정보에 해당한다.
LLM이 새로운 토큰을 생성할 때는 현재 토큰의 Query를 이용해 이전 토큰들의 Key와 비교하고, 그 결과를 바탕으로 Value를 가져와 다음 출력을 계산한다.
따라서 이전 토큰에서 만들어진 Key와 Value를 다시 사용할 수 있다면 같은 계산을 반복할 필요가 없다.
그래서 LLM은 이전 토큰에서 계산한 K와 V를 메모리에 저장해 둔다.
바로 이 Key와 Value를 Cache에 저장하기 때문에 이름이 KV Cache다.
여기서 중요한 것은 Query는 일반적으로 같은 방식으로 계속 저장할 필요가 없다는 점이다.
새로운 토큰이 생성될 때 현재 토큰의 Query가 만들어지고, 이미 저장되어 있는 이전 토큰들의 Key와 Value를 활용해 Attention을 계산하기 때문이다.
예를 들어 "오늘 서울의 날씨는"이라는 문장을 처리했다고 생각해 보자.
이때 각 토큰에 대해 만들어진 Key와 Value가 Cache에 쌓이고, 다음 토큰을 생성할 때 새롭게 만들어진 Query가 이 정보들을 참고한다.
이전 토큰
↓
Key ─────┐
Value ───┤ → KV Cache
│
새로운 토큰 → Query ──→ Attention
↓
다음 토큰 생성
따라서 KV Cache라는 이름 자체가 이 기술의 구조를 그대로 설명하고 있다.
Key와 Value를 저장(Cache)해 두었다가 다음 토큰 생성에서 재사용하는 것이다.
한 토큰씩 답을 만드는 LLM
LLM은 질문을 입력 받았다고 해서 한 번에 완성된 문장을 만들어 내지 않는다.
입력된 내용을 분석한 뒤 다음에 올 토큰 하나를 선택하고, 그 토큰을 다시 입력으로 사용해 다음 토큰을 생성한다.
예를 들어 "오늘 서울의 날씨는"이라는 입력이 들어왔다고 생각해 보자.
모델은 먼저 “맑고“라는 토큰을 선택하고, 다음에는 “좋습니다” 와 같은 토큰을 선택하는 과정을 반복한다.
이 과정에서 이전 토큰들의 정보를 계속 참고해야 한다.
문제는 이전 토큰이 많아질수록 매번 모든 정보를 다시 계산한다면 불필요한 연산이 반복된다는 것이다.
이미 계산한 정보를 버리지 않는다
그렇다면 왜 이전에 계산한 정보를 굳이 메모리에 남겨야 할까? 이유는 다음 토큰을 생성할 때 이전 토큰들의 Key와 Value가 다시 필요하기 때문이다.
다음 토큰을 생성할 때 이전 토큰의 Key와 Value는 다시 계산하지 않아도 되기 때문에 이 값을 메모리에 저장해 둔다.
예를 들어 1,000개의 토큰을 처리한 상태라면 1,000개 토큰에 대한 Key와 Value가 이미 만들어져 있다.
1,001번째 토큰을 생성할 때 이 정보를 버리지 않고 그대로 사용하면 이전 1,000개 토큰에 대한 계산을 반복할 필요가 없다.
이렇게 이전 계산 결과를 저장해 두는 공간이 KV Cache다.
속도를 얻는 대신, 계산 결과를 계속 보관하기 위한 메모리가 필요해지는 것이다.
토큰이 늘어나면 LLM KV Cache도 늘어난다
여기서 중요한 특징이 하나 있다.
KV Cache는 모델을 한 번 로딩하고 끝나는 고정된 메모리가 아니라 Context가 증가하면서 함께 커지는 메모리라는 것이다.
예를 들어 사용자가 처음에는 100개의 토큰으로 질문했다면 비교적 작은 Cache만 필요하다.
그런데 대화가 계속 이어져 Context가 4,000토큰, 8,000토큰으로 늘어나면 저장해야 하는 Key와 Value도 계속 증가한다.
100 tokens → 작은 KV Cache
1,000 tokens → 더 큰 KV Cache
4,000 tokens → 상당히 큰 KV Cache
16,000 tokens → 훨씬 큰 KV Cache
따라서 Context Window를 크게 만든다고 해서 모델의 가중치만 커지는 것이 아니다.
실제 추론 과정에서 유지해야 하는 LLM KV Cache의 크기도 함께 증가한다.
긴 문서를 넣으면 문제가 더 커진다
예를 들어 20페이지짜리 기술 문서를 LLM에게 입력하고 그 내용을 분석하도록 한다고 생각해 보자.
문서 자체가 상당히 많은 토큰으로 변환되기 때문에 Attention에서 관리해야 할 Key와 Value도 많아진다.
여기에 사용자가 "그 내용을 다시 요약해줘"라고 추가 질문을 하면 새로운 토큰을 생성하면서 기존 Context의 KV Cache를 계속 활용하게 된다.
즉, 긴 문서를 처리하는 순간부터 모델의 가중치와 별개로 상당한 추론 메모리가 필요할 수 있다.
그래서 LLM에서 말하는 긴 Context 지원은 단순히 모델이 더 많은 문자를 읽을 수 있다는 의미가 아니다.
그만큼 많은 Attention 정보를 메모리에 유지하면서 처리할 수 있는 실행 환경도 필요하다는 의미다.
한 명이 아니라 100명이 사용한다면
서버 환경에서는 문제가 더욱 커진다.
한 명의 사용자가 긴 Context를 사용하는 것과 100명의 사용자가 동시에 긴 Context를 사용하는 것은 전혀 다른 문제이기 때문이다.
예를 들어 하나의 요청이 상당한 크기의 LLM KV Cache를 사용한다고 가정해 보자. 동시에 10개의 요청이 유지된다면 필요한 Cache 메모리 역시 단순하게 생각해도 여러 배로 증가한다.
요청이 50개, 100개로 증가하면 모델 가중치는 그대로인데도 추론에 필요한 메모리는 계속 증가할 수 있다.
이 때문에 LLM 서버에서는 모델 크기뿐 아니라 동시 요청 수와 각 요청의 Context 길이를 함께 고려해야 한다.
모델 하나를 GPU에 올릴 수 있다고 해서 반드시 많은 사용자를 동시에 처리할 수 있는 것은 아니다.
그래서 메모리를 미리 확보하기도 한다
추론 엔진에서는 LLM KV Cache를 요청이 발생할 때마다 무작정 메모리에 할당하는 방식만 사용하는 것은 효율적이지 않다.
반복적인 메모리 할당과 해제는 실행 성능과 메모리 관리에 부담을 줄 수 있기 때문이다.
예를 들어 여러 요청이 들어오는 서버라면 Cache를 일정한 단위로 관리하고 필요한 공간을 재사용하는 방식이 필요하다.
사용자가 대화를 종료하거나 Context가 더 이상 필요하지 않다면 해당 영역을 회수해 다른 요청에 사용할 수도 있다.
결국 LLM KV Cache는 연산 문제이면서 동시에 메모리 관리 문제다.
좋은 추론 엔진은 Attention을 빠르게 계산하는 것뿐 아니라 Cache를 어떻게 배치하고 재사용할지도 고민해야 한다.
LLM KV Cache를 줄이는 방법도 있다
그렇다면 LLM KV Cache의 메모리 사용량을 무조건 감수해야 할까?
실제로는 GQA나 MQA처럼 Key와 Value의 개수를 줄이는 구조를 사용하거나 KV Cache 자체를 낮은 정밀도로 저장하는 방법도 있다.
예를 들어 모든 값을 높은 정밀도로 저장하는 대신 필요한 정확도를 유지하면서 더 작은 데이터 형식으로 저장하면 Cache가 차지하는 공간을 줄일 수 있다.
또한 긴 Context 전체를 무조건 동일하게 유지하지 않고 실제 사용 패턴에 맞춰 관리하는 방법도 중요하다.
이런 기술들은 결국 하나의 목표를 향한다.
LLM의 답변 품질과 생성 속도를 유지하면서 얼마나 적은 메모리로 많은 Context를 처리할 것인가다.
사람의 추론과 LLM KV Cache는 무엇이 비슷하고 다른가
사람도 문제를 해결할 때 이전에 생각했던 내용을 모두 버리고 처음부터 다시 생각하지 않는다.
앞에서 얻은 정보와 경험을 기억하고, 새로운 정보가 들어오면 기존 내용과 연결하면서 다음 판단을 만들어 간다.
LLM의 KV Cache도 비슷한 모습을 보인다.
앞에서 처리한 토큰의 Key와 Value를 저장해 두었다가 새로운 토큰을 생성할 때 다시 활용하기 때문이다.
예를 들어 사람이 긴 대화를 하면서 앞에서 이야기한 내용을 기억하고 있다면, 매번 대화의 첫 문장부터 다시 읽을 필요가 없다.
LLM KV Cache에 저장된 이전 Attention 정보를 활용하기 때문에 이미 처리한 내용을 반복해서 계산하지 않는다.
하지만 사람의 기억과 KV Cache는 근본적으로 다르다.
사람의 기억은 중요한 정보와 의미를 추상화하고 필요에 따라 일부를 잊거나 재구성할 수 있지만, KV Cache는 추론 과정에서 계산된 수치 정보를 그대로 저장하고 재사용하는 구조에 가깝다.
사람은 오래된 기억을 압축하거나 경험을 통해 새로운 개념으로 재구성할 수 있다.
반면 KV Cache는 Context가 길어질수록 저장해야 할 데이터가 계속 증가하기 때문에, 결국 컴퓨터 메모리라는 물리적인 한계에 부딪힌다.
그래서 흥미로운 차이가 생긴다.
사람은 기억을 활용해 생각을 이어가지만, LLM은 계산 결과를 저장해 계산을 줄인다.
이 관점에서 보면 KV Cache는 단순한 성능 최적화 기술이 아니다.
LLM이 이전 정보를 어떻게 유지하면서 다음 추론으로 넘어가는지를 보여주는, 기계의 독특한 ‘기억 방식’이라고 볼 수 있다.
LLM의 메모리는 모델 크기로 끝나지 않는다
KV Cache가 계속 메모리를 요구하는 이유는 단순하다.
LLM이 이전 토큰의 Attention 정보를 버리지 않고 다음 토큰 생성에 재사용하기 때문이다.
Context가 길어질수록 저장해야 할 정보가 늘어나고, 동시에 처리하는 요청이 많아질수록 필요한 Cache도 함께 증가한다.
그래서 LLM 추론에서 메모리는 단순히 모델을 올려놓는 공간이 아니라 추론 과정 자체를 유지하기 위한 실행 공간이 된다.
LLM의 성능을 높인다는 것은 단순히 연산을 빠르게 만드는 것만을 의미하지 않는다.
계산을 줄이기 위해 어떤 정보를 저장하고, 얼마나 오래 유지하며, 언제 버릴 것인가를 결정하는 것 역시 추론 엔진의 중요한 기술이다.
[글에서 사용한 머리 아픈 용어]
- Attention(어텐션): 입력된 토큰들 사이의 관계를 계산해 현재 토큰이 어떤 정보를 중요하게 참고해야 하는지 결정하는 Transformer의 핵심 연산입니다.
- Context: LLM이 현재 응답을 생성하기 위해 참고하고 있는 입력과 이전 대화 등의 정보 범위입니다. Context가 길어질수록 관리해야 하는 Attention 정보도 증가할 수 있습니다.
- Context Window: LLM이 하나의 요청에서 처리하고 유지할 수 있는 최대 토큰 범위입니다. Context Window가 커질수록 긴 문서나 긴 대화를 처리할 수 있지만, 추론 과정에서 필요한 메모리도 증가할 수 있습니다.
- Token(토큰): LLM이 텍스트를 처리하는 기본 단위입니다. 하나의 단어가 하나의 토큰일 수도 있지만, 단어의 일부나 여러 문자가 하나의 토큰으로 처리될 수도 있습니다.
- Quantization(양자화): 모델의 가중치나 KV Cache 등의 데이터를 더 낮은 정밀도의 데이터 형식으로 표현해 메모리 사용량과 연산 비용을 줄이는 기술입니다.
- Memory Fragmentation(메모리 단편화): 메모리를 반복적으로 할당하고 해제하는 과정에서 사용 가능한 메모리가 여러 작은 영역으로 나뉘어 효율적으로 사용하기 어려워지는 현상입니다.
- Inference Runtime(추론 런타임): 학습이 끝난 AI 모델을 실제 하드웨어에서 실행할 수 있도록 모델 로딩, 연산, 메모리, 실행 과정 등을 관리하는 소프트웨어 환경입니다.
※ 특정 산업이나 자산에 대한 투자 판단은 본인의 책임 하에 신중히 결정하시기 바랍니다.