SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-13

KV 캐시와 프롬프트 캐시 차이점 완벽 정리

KV 캐시는 요청마다 서버 RAM을 점유하는 작업 메모리이며 부족 시 모델 로딩이 실패합니다. 반면 프롬프트 캐시는 비용 절감을 위한 서비스로 캐시 적중 실패 시 정가를 지불할 뿐입니다. 두 개념의 기술적 차이와 메모리 점유 원리를 상세히 설명합니다.

KV 캐시와 프롬프트 캐시: 요약

KV 캐시와 제공업체의 프롬프트 캐시는 이름만 비슷할 뿐 사실상 완전히 다른 개념입니다. KV 캐시는 요청 단위의 작업 메모리입니다. 요청이 처리되는 동안 서버의 RAM이나 VRAM에 상주하며, 컨텍스트 길이와 동시 요청 수에 비례하여 크기가 증가합니다. 반면 제공업체의 프롬프트 캐싱은 비용 절감과 지연 시간 단축을 위한 기능입니다. 프롬프트의 고정된 접두사(prefix)를 제공업체 서버에 저장해 두었다가, 동일한 내용을 다시 보낼 때 할인된 요금을 적용받는 방식입니다.

하나는 직접 하드웨어로 구매하는 메모리이고, 다른 하나는 타인이 보유한 메모리에 대해 사용료를 지불하는 서비스입니다.

정의보다 실질적인 차이가 더 중요합니다. KV 캐시는 용량이 부족해지면 모델 로딩이 실패하거나 요청이 거부됩니다. 반면 프롬프트 캐시는 용량이 부족해지는 일이 없습니다. 캐시 적중(hit)에 실패할 뿐이며, 이 경우 단순히 정가를 지불하게 됩니다.

KV 캐시의 역할과 존재 이유

500번째 토큰을 생성하는 트랜스포머 모델은 그 앞의 499개 토큰 전체를 어텐션(attention)해야 합니다. 각 토큰마다 모든 레이어는 키 벡터와 값 벡터를 필요로 합니다. 새로운 토큰이 생성될 때마다 이 모든 벡터를 다시 계산하면 생성 시간은 토큰 길이의 제곱에 비례하여 증가하므로, 런타임은 이를 메모리에 유지합니다. 이 저장소가 바로 KV 캐시(key/value cache)입니다.

KV 캐시는 요청별로 생성되는 상태값이며, 해당 요청의 정확한 토큰 시퀀스를 기반으로 구축됩니다. 따라서 서로 다른 프롬프트를 보내는 두 사용자는 이를 공유할 수 없습니다. 단, 뒤에서 설명할 별도의 기능인 프리픽스 캐싱(prefix caching)을 런타임이 수행하는 경우는 예외입니다.

서비스 제공은 두 단계로 나뉩니다. 프리필(prefill) 단계는 전체 프롬프트를 읽어 캐시를 채우며, 연산 성능에 의해 속도가 제한됩니다. 디코드(decode) 단계는 한 번에 하나의 토큰을 생성하여 캐시에 추가하며, 메모리 대역폭에 의해 속도가 제한됩니다. 이러한 구분 때문에 프롬프트 처리와 토큰 생성 시 직접 초당 토큰 수를 측정할 때 서로 다른 속도가 보고되는 것입니다.

KV 캐시는 메모리를 얼마나 사용합니까?

벤더가 제공하는 표를 찾을 필요는 없습니다. 크기는 산술적으로 계산할 수 있으며, 어떤 모델이든 직접 다시 계산할 수 있습니다.

bytes per token = 2 * layers * kv_heads * head_dim * bytes per element

여기서 2는 키(key)와 값(value)을 의미합니다. 나머지 모든 숫자는 모델의 Hugging Face 페이지에 게시된 모델의 config.json에서 가져옵니다.

Llama 3.1 8B를 예로 들어보겠습니다. 설정에는 num_hidden_layers 32와 num_key_value_heads 8이 명시되어 있습니다. hidden_size 4096을 32개의 어텐션 헤드로 나누면 헤드 차원은 128이 됩니다. f16 정밀도에서 각 요소는 2바이트를 차지합니다.

2 * 32 * 8 * 128 * 2 = 131072 bytes = 128 KiB per token

이 값을 요청하려는 컨텍스트 길이와 동시에 실행하는 요청 수에 곱하십시오.

ChartLlama 3.1 8B KV cache at f16, in GiB
The data behind this chart
[
  {
    "label": "2k context",
    "one_request_gib": 0.25,
    "four_requests_gib": 1
  },
  {
    "label": "8k context",
    "one_request_gib": 1,
    "four_requests_gib": 4
  },
  {
    "label": "32k context",
    "one_request_gib": 4,
    "four_requests_gib": 16
  },
  {
    "label": "128k context",
    "one_request_gib": 16,
    "four_requests_gib": 64
  }
]

8k 컨텍스트에서 캐시 크기는 1 GiB입니다. 32k에서는 4 GiB가 되며, 이는 4비트 가중치 자체와 비슷한 범위입니다. 모델의 최대 컨텍스트인 128k에서는 단일 요청당 16 GiB를 사용하며, 4개의 요청이 각각 이를 채울 경우 64 GiB를 사용합니다. 가중치는 변하지 않았지만 캐시만 증가한 것입니다.

그룹화된 쿼리 어텐션(GQA)이 이 수치에서 큰 역할을 합니다. Llama 3.1 8B는 32개의 쿼리 헤드를 지원하는 8개의 키/값 헤드를 가지고 있으므로, 4개의 쿼리 헤드가 하나의 저장된 키/값 쌍을 공유합니다. num_key_value_headsnum_attention_heads와 같은 모델은 동일한 파라미터 수에서도 4배 더 많은 캐시를 사용합니다. 두 개의 8B 모델을 서비스하는 비용이 같다고 가정하기 전에 해당 필드를 먼저 확인하십시오.

2k에서 실행되던 모델이 32k에서 로드되지 않는 이유

런타임은 모델이 로드될 때 실제 입력하는 프롬프트가 아닌, 설정한 컨텍스트 길이에 맞춰 KV 캐시를 미리 예약하기 때문입니다. Ollama의 기본 컨텍스트 윈도우는 4096 토큰입니다. 이를 32k로 높이면 단 하나의 토큰이 도착하기도 전에 4 GiB의 추가 메모리 할당을 요청하게 됩니다.

OLLAMA_CONTEXT_LENGTH=32768 ollama serve

대화형 프롬프트에서 세션별로 동일한 설정을 적용하는 방법입니다:

ollama run llama3.1:8b
/set parameter num_ctx 32768

실패 양상은 스택마다 다르게 나타납니다. vLLM은 시작 시점에 연산을 확인하고 실행을 거부합니다:

ValueError: The model's max seq len (131072) is larger than the maximum number of tokens that can be stored in KV cache (78336). Try increasing `gpu_memory_utilization` or decreasing `max_model_len` when initializing the engine.

CPU 전용 VPS에서는 이러한 확인 절차가 없습니다. 할당이 일반적인 시스템 RAM에서 이루어지기 때문입니다. 대신 커널의 out-of-memory killer가 해당 프로세스를 강제 종료하며, 커널 링 버퍼에 다음과 같은 흔적을 남깁니다:

dmesg -T | grep -i "killed process"

서빙 프로세스를 지목하는 줄이 나타난다면, 해당 서버가 보유한 메모리보다 더 많은 메모리를 할당하려 했다는 의미입니다. 해결책은 스왑 파일을 늘리는 것이 아니라 컨텍스트 크기를 줄이는 것입니다. 디스크로 페이징된 KV 캐시는 토큰이 생성될 때마다 읽어야 하므로, 생성 속도가 사실상 사용 불가능할 정도로 느려집니다. 적절한 값을 선택하는 방법은 Ollama의 num_ctx 및 컨텍스트 길이 가이드에서 다룹니다.

동시성이 수치에 미치는 영향

진행 중인 모든 요청은 각자의 KV cache를 점유합니다. 이는 대부분의 용량 계획에서 간과하는 부분입니다. 32k 컨텍스트를 유지하는 사용자 4명은 모델 가중치 외에도 16 GiB의 메모리를 추가로 필요로 합니다.

런타임마다 이 제약의 엄격함은 다릅니다. Ollama와 llama.cpp는 모델이 로드될 때 요청한 컨텍스트만큼을 미리 예약하므로, 실제 사용 여부와 관계없이 메모리가 할당됩니다. 반면 vLLM은 풀을 고정 크기 블록으로 나누어 요청이 증가함에 따라 배분하므로, 500 토큰 요청은 500 토큰만큼의 메모리만 점유합니다. 어떤 방식이든 풀은 유한하며, 가득 차면 새로운 요청은 실행되지 않고 대기열에 들어갑니다. 이러한 대기열이 응답 시간에 미치는 영향은 자체 호스팅 LLM이 처리할 수 있는 동시 사용자 수에서 다룹니다.

KV 캐시 크기를 줄이는 4가지 방법

  1. 컨텍스트 길이를 줄입니다. 이는 가장 큰 영향을 미치는 요소이며 보통 가장 비용이 적게 듭니다. 대부분의 채팅 작업은 32k에 근접하지도 않습니다.
  2. 캐시 자체를 양자화합니다. Ollama의 OLLAMA_KV_CACHE_TYPE는 기본값이 f16이며, 메모리를 절반 정도 사용하는 q8_0과 4분의 1을 사용하는 q4_0을 지원합니다. llama.cpp의 대응 설정은 -ctk q8_0-ctv q8_0입니다.
  3. 키/값 헤드나 레이어 수가 적은 모델을 선택합니다. 40 GB의 가중치를 다운로드하기 전에 config.json을 읽어보십시오.
  4. 동시에 처리하는 요청 수를 줄이고 나머지는 대기열에 넣습니다.

q4_0에서 Llama 3.1 8B 수치는 토큰당 128 KiB에서 약 32 KiB로 감소하므로, 32k 컨텍스트는 4 GiB 대신 약 1 GiB의 비용이 듭니다. 이러한 절감에는 대가가 따릅니다. 키와 값이 낮은 정밀도로 저장되므로, 설정을 유지하기 전에 직접 프롬프트를 사용하여 출력 결과를 비교하십시오.

프로바이더 프롬프트 캐싱의 실제 이점

프로바이더 프롬프트 캐싱은 기존과 다른 과금 단위를 사용하는 별개의 제품입니다. 안정적인 접두사(prefix)를 지정하면 프로바이더가 이를 저장하고, 이후 동일한 접두사를 반복하는 호출에 대해 전체 입력 가격이 아닌 할인된 요금을 청구합니다.

2026년 8월 기준 Anthropic이 공개한 배율은 다음과 같습니다. 5분 캐시 쓰기 비용은 기본 입력 토큰 가격의 1.25배입니다. 1시간 쓰기 비용은 2배이며, 캐시 읽기 비용은 0.1배입니다. 20,000 토큰 규모의 시스템 프롬프트를 이 수치에 대입하면 거래의 경제성이 명확해집니다.

ChartCost of a 20,000 token prefix, in base input token equivalents
The data behind this chart
[
  {
    "label": "No caching, every call",
    "billed_token_equivalents": "20,000"
  },
  {
    "label": "First call, 5 minute cache write",
    "billed_token_equivalents": "25,000"
  },
  {
    "label": "First call, 1 hour cache write",
    "billed_token_equivalents": "40,000"
  },
  {
    "label": "Every later call, cache hit",
    "billed_token_equivalents": "2,000"
  }
]

이를 산술적으로 계산해 보십시오. 5분 캐시 쓰기 프리미엄은 첫 호출 시 5,000 토큰에 해당합니다. 캐싱 없이 전송할 때의 20,000와 비교하여 25,000가 청구됩니다. 유효 기간 내의 모든 후속 호출은 20,000 대신 2,000만 청구되므로 18,000 토큰을 절약하게 됩니다. 따라서 5분 캐시는 두 번째 호출부터 이득이 발생합니다.

1시간 캐시는 다른 전략입니다. 쓰기 시 40,000가 청구되며, 이는 20,000 토큰에 해당하는 프리미엄이므로 이득을 보려면 1시간 내에 두 번의 적중(hit)이 필요합니다. 이는 모델의 문제가 아니라 사용자의 트래픽 패턴에 관한 문제입니다. 윈도우 선택 방법을 포함한 전체 계산식은 Claude 프롬프트 캐싱의 손익분기점 계산에서 확인할 수 있습니다.

캐시 적중 여부를 결정하는 두 가지 세부 사항이 있습니다. 첫째, 모델의 최소 길이 미만인 접두사는 자동으로 캐싱되지 않습니다. 2026년 8월 기준 명시된 최소 길이는 Claude Opus 5의 경우 512 토큰, Claude Sonnet 5의 경우 1,024 토큰이며, 이보다 짧은 요청은 오류 없이 정상적으로 처리됩니다. 둘째, 수명은 항목을 쓰거나 읽는 요청이 시작된 시점부터 측정되며, 읽기가 발생할 때마다 추가 비용 없이 수명이 갱신됩니다. 따라서 트래픽이 많은 엔드포인트는 5분 캐시를 무기한 유지할 수 있습니다. 반면 10분마다 한 번씩 호출되는 엔드포인트는 매번 쓰기 프리미엄을 지불하게 되며 캐시 혜택을 전혀 받지 못합니다.

가정하지 말고 응답을 직접 확인하십시오. usage 객체는 cache_creation_input_tokenscache_read_input_tokens를 보고합니다. 모든 호출에서 읽기 횟수가 0이라면, 쓰기 비용만 지불하고 아무런 혜택도 얻지 못하고 있는 것입니다.

두 캐시가 만나는 지점

긴 시스템 프롬프트는 두 캐시가 만나는 장소이며, 양쪽 모두에 비용을 발생시킵니다.

로컬 환경에서 20,000 토큰의 시스템 프롬프트는 Llama 3.1 8B 서버의 f16 설정에서 약 2.4 GiB의 KV 캐시를 점유하며, 이를 포함하는 모든 동시 요청마다 개별적으로 공간을 차지합니다. 원격 환경에서는 동일한 접두사가 한 번의 캐시 쓰기 비용을 발생시키고, 이후 호출마다 입력 토큰의 0.1배만큼 비용이 발생합니다. 로컬 비용은 사용자 수에 비례하여 증가합니다. 원격 비용은 트래픽 양에 비례하며 유휴 시간에는 초기화됩니다.

제공자의 프롬프트 캐싱과 유사하여 혼동하기 쉬운 로컬 기능으로 접두사 캐싱(prefix caching)이 있습니다. vLLM 문서에서는 자동 접두사 캐싱을 "기존 쿼리의 KV 캐시를 캐싱하여, 새로운 쿼리가 기존 쿼리와 동일한 접두사를 공유할 경우 KV 캐시를 직접 재사용할 수 있게 하는 것"으로 설명합니다. llama.cpp 서버는 기본적으로 슬롯당 프롬프트 캐시를 유지하며, --cache-reuse N은 재사용을 시도할 최소 청크 단위를 설정합니다.

접두사 캐싱은 프리필(prefill) 연산 비용을 절감합니다. 20,000 토큰의 시스템 프롬프트를 매 요청마다 처리하는 대신 한 번만 처리하므로, 첫 번째 토큰이 생성되기까지의 시간이 크게 단축됩니다. vLLM에서는 공유 블록이 복제되지 않고 재사용되므로 메모리 효율성도 개선됩니다. 하지만 이 기능이 현재 활성화된 토큰을 위해 유지해야 하는 캐시 크기를 줄여주지는 않습니다. 요청 사이에 모델 가중치를 상주시키는 것은 이와 관련이 있지만 별개의 수단이며, 요청 사이에 Ollama 모델 유지하기에서 다룹니다.

자신의 서버에서 측정해야 할 항목

대상 컨텍스트에서 모델을 로드한 뒤, 추정치에 의존하지 말고 실제 수치를 확인하십시오.

ollama ps
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
free -g

ollama ps은 로드된 모델의 크기와 GPU 또는 CPU에서 실행 중인지 여부를 나열합니다. GPU에 완전히 올라갈 것으로 예상했던 모델이 CPU 분할을 보고한다면, KV 캐시가 모델의 일부를 밀어냈다는 의미이며 생성 속도는 그에 따라 저하됩니다. nvidia-smi은 실제 VRAM 수치를 제공하며, free -g는 CPU 전용 VPS에서 동일한 작업을 수행합니다. 컨텍스트를 단계별로 높이고 다시 로드하면서 수치 변화를 관찰하십시오. 직접 계산한 값과 보고된 수치는 서로 비슷해야 합니다. 만약 그렇지 않다면, 그 차이는 공식의 오류라기보다 런타임 자체의 연산 버퍼 때문인 경우가 많습니다.

이러한 수치로 인해 대여하고 싶지 않은 사양의 하드웨어를 사용해야 하는 상황이라면, 토큰당 비용을 지불하는 방식과의 비교 내용을 GPU VPS와 API 토큰 비용 비교에서 확인하십시오.

FAQ

KV 캐시와 프롬프트 캐싱은 같은 것입니까?

아닙니다. KV 캐시는 서비스 프로세스 내부에서 요청별로 사용하는 메모리로, 현재 컨텍스트의 모든 토큰에 대한 키와 값 벡터를 보관합니다. 이는 RAM이나 VRAM에 상주하며 요청이 종료되면 해제됩니다. 제공자의 프롬프트 캐싱은 안정적인 프롬프트 접두사를 제공자의 인프라에 저장하고, 이를 다시 보낼 때 할인된 요금을 부과하는 과금 기능입니다. KV 캐시가 부족하면 모델을 로드할 수 없습니다. 프롬프트 캐시를 사용하지 못하면 청구 금액이 늘어나고 첫 토큰 생성 시간(TTFT)이 길어질 뿐입니다.

왜 모델이 2k 컨텍스트에서는 로드되는데 32k에서는 실패합니까?

런타임이 로드 시점에 실제 보낸 프롬프트가 아닌 설정한 컨텍스트 길이에 맞춰 전체 KV 캐시를 할당하기 때문입니다. Llama 3.1 8B 모델을 f16으로 실행할 때 캐시는 토큰당 128 KiB를 차지하므로, 2k 컨텍스트는 0.25 GiB, 32k 컨텍스트는 4 GiB가 필요합니다. 모델 가중치는 두 경우 모두 적재 가능하지만, 메모리 예약 단계에서 실패가 발생합니다. vLLM은 이를 ValueError으로 보고하며 저장 가능한 최대 토큰 수를 명시하고, gpu_memory_utilization을 높이거나 max_model_len를 낮출 것을 제안합니다. CPU 전용 환경에서는 커널의 out-of-memory killer가 프로세스를 강제 종료하며, 이는 dmesg -T | grep -i "killed process"으로 확인할 수 있습니다.

모델의 KV 캐시 크기는 어떻게 계산합니까?

레이어 수, 키/값 헤드 수, 헤드 차원, 요소당 바이트 수를 모두 곱한 뒤 2를 곱하십시오. 이것이 토큰당 바이트 수입니다. 여기에 컨텍스트 길이와 동시 요청 수를 곱하십시오. 레이어와 헤드 수는 모델의 config.json에서 확인하십시오. f16이나 bf16의 경우 요소당 2바이트를 사용합니다. q8_0 캐시는 그 절반 정도이며, q4_0은 약 4분의 1 수준입니다.

프롬프트 캐싱이 내 서버의 메모리 사용량을 줄여줍니까?

제공자의 프롬프트 캐싱은 저장소가 제공자 측에 있으므로 하드웨어 자원에는 아무런 영향을 주지 않습니다. 로컬 환경에서의 대응 기술은 vLLM과 llama.cpp 서버에서 제공하는 접두사 캐싱(prefix caching)입니다. 이는 공유 접두사에 대해 이미 계산된 키와 값 벡터를 재사용하여 프리필(prefill) 연산을 줄이고 첫 토큰 생성 시간을 단축합니다. vLLM은 공유 블록을 복제하지 않고 재사용하므로 메모리 효율도 개선됩니다. 다만 두 기능 모두 현재 처리 중인 토큰에 필요한 캐시 크기를 줄여주지는 않으므로, 컨텍스트와 동시성 계산에 따른 최소 메모리 요구량은 여전히 유지됩니다.

한 번만 보내는 프롬프트를 캐싱할 가치가 있습니까?

없습니다. 2026년 8월 기준 5분 옵션의 경우 캐시 쓰기 비용이 기본 입력 비용의 1.25배이므로, 해당 시간 내에 다시 보내지 않을 접두사를 캐싱하는 것은 손해입니다. 캐싱은 긴 시스템 프롬프트나 여러 번 질문할 문서처럼 동일한 접두사가 반복될 때 이득이 됩니다. API 응답의 cache_read_input_tokens을 확인하여 쓰기 비용을 지불하는 대신 캐시 적중(hit)이 발생하고 있는지 확인하십시오.