llama.cpp 컨텍스트 길이와 KV 캐시, GPU 오프로딩만으로 해결되지 않는 메모리 문제

그래픽카드와 메모리 모듈, 전원 케이블이 보이는 로컬 LLM 추론용 데스크톱 워크스테이션 대표 이미지 1

AI를 활용하여 생성한 이미지입니다.

AI · LLM · 중급 가이드

로컬 LLM을 돌릴 때 모델 파일 크기만 보고 메모리를 계산하면 자주 빗나가요. 모델이 GPU에 올라갔는데도 긴 대화에서 갑자기 느려지거나, 짧은 요청은 되는데 동시 요청에서 메모리가 넘치는 이유는 컨텍스트와 KV 캐시가 따로 자리를 차지하기 때문이에요. Ollama·LM Studio·llama.cpp의 입문 선택 기준은 기초 비교 글에서 다뤘고, 여기서는 llama.cpp 계열 서버를 직접 조정할 때 필요한 기준을 정리할게요.

모델 메모리와 실행 메모리는 다르다

llama.cpp는 1.5비트부터 8비트까지 여러 정수 양자화 형식을 지원하고, GPU 메모리보다 모델이 클 때 CPU와 GPU를 나눠 쓰는 하이브리드 실행도 지원해요.[1] 그래서 Q4나 Q8 파일 크기는 시작점이지 전체 사용량이 아니에요.

실행 중에는 모델 가중치 외에 컨텍스트를 저장하는 KV 캐시, 입력을 처리하는 배치 버퍼, 출력과 런타임 오버헤드가 추가돼요. 특히 긴 대화를 유지하거나 여러 요청을 동시에 받으면 KV 캐시와 배치 관련 메모리가 커져요. 같은 양자화 모델이라도 ctx-size, 동시 슬롯 수, 배치 크기에 따라 실제 여유가 달라지는 이유예요.

ctx-size는 품질 옵션이 아니라 자원 계약이에요

llama-server-c, --ctx-size는 프롬프트 컨텍스트 크기를 정하고, 0이면 모델에서 읽은 기본값을 사용해요.[2] 컨텍스트를 크게 잡으면 긴 문서를 한 번에 넣을 여지가 생기지만, 실제 대화가 짧은데도 큰 값을 예약하면 다른 작업에 쓸 메모리가 줄어들 수 있어요.

./llama-server -m ./models/model.gguf   --host 127.0.0.1 --port 8080   -c 8192 -ngl 99

처음부터 128K 같은 큰 값을 넣기보다 실제 입력 길이의 두 배 정도로 시작해요. 요약·코딩·검색 보조처럼 목적이 다른 작업은 필요한 문맥 길이가 달라요. 긴 문서를 넣어야 한다면 한 번에 모두 넣는 대신 검색으로 필요한 부분을 골라 보내는 편이 메모리와 응답 시간을 함께 줄일 수 있어요.

KV 캐시가 긴 대화에서 문제를 만드는 방식

KV 캐시는 이미 처리한 토큰의 어텐션 상태를 저장해 다음 토큰을 만들 때 다시 계산하지 않도록 도와줘요. 덕분에 대화가 이어질수록 매번 처음부터 계산하지 않지만, 저장해야 할 토큰이 늘어나면 메모리도 늘어나요. 모델 가중치를 GPU에 전부 올렸다는 사실만으로 긴 문맥이 안전해지는 건 아니에요.

증상은 대체로 이렇게 나타나요.

  • 짧은 질문은 빠른데 대화가 길어질수록 토큰 생성 속도가 떨어져요.
  • 모델을 불러오는 데는 성공하지만 두 번째 동시 요청에서 메모리 부족이 나요.
  • 컨텍스트를 늘린 뒤 화면이 멈추거나 운영체제가 메모리를 압박해요.

이때 양자화를 더 낮추기 전에 -c를 실제 사용량에 맞추고, 동시 슬롯과 배치 옵션을 보수적으로 줄이는 게 먼저예요. 품질이 필요한 작업에서 무조건 더 작은 양자화를 고르면 속도는 남아도 답변 품질이 떨어질 수 있어요.

GPU 오프로딩은 0 또는 100이 아니에요

llama.cpp의 -ngl은 GPU에 올릴 레이어 수를 조절하는 대표 옵션이에요. GPU 메모리가 충분하면 많은 레이어를 올릴 수 있지만, KV 캐시와 런타임 버퍼까지 포함한 여유가 있어야 해요. 일부 레이어만 GPU에 두는 CPU+GPU 혼합 실행도 모델이 VRAM보다 큰 경우의 선택지예요.[1][2]

다음처럼 단계적으로 확인해요.

  1. 작은 컨텍스트와 낮은 동시성으로 서버를 먼저 띄워요.
  2. -ngl을 올리면서 로딩 성공 여부와 생성 속도를 기록해요.
  3. 컨텍스트를 늘린 뒤 같은 프롬프트를 다시 보내 메모리 증가와 속도 변화를 비교해요.
  4. 동시 요청을 추가해 한 슬롯과 여러 슬롯의 차이를 확인해요.

첫 요청만 빠르고 두 번째 요청부터 느려진다면 GPU 오프로딩 자체보다 동시 슬롯과 KV 캐시가 병목일 수 있어요. 반대로 GPU 메모리가 부족해 일부 레이어가 CPU로 내려가면 토큰 생성이 느려질 수 있으니, 속도와 안정성 중 무엇이 필요한지 먼저 정해야 해요.

Ollama를 앞에 둘 때 확인할 것

Ollama FAQ는 모델이 GPU에 올라갔는지 확인하는 방법과 모델을 메모리에서 내리는 관리 명령을 안내해요.[3] Ollama를 사용하면서 내부 서버의 세부 옵션까지 직접 만지려 하면 같은 모델이 여러 프로세스에 중복 로드됐는지부터 확인해야 해요.

ollama ps
ollama stop 모델이름

OpenAI 호환 클라이언트나 자동화 도구를 붙일 때는 서버가 실제로 열어 둔 주소와 API 형식을 확인해요. llama-server는 기본적으로 127.0.0.1:8080에서 시작하고 OpenAI 호환 엔드포인트를 제공한다고 문서에 나와 있어요.[2] Ollama도 API 문서에서 로컬 API와 모델 생성·채팅 요청 형식을 별도로 설명해요.[4] 호환된다는 말이 곧 모든 파라미터가 같다는 뜻은 아니어서, 클라이언트의 컨텍스트·출력 길이 옵션이 서버에 실제로 전달되는지 확인해야 해요.

문제 재현표를 만들면 선택이 쉬워요

시험 고정할 값 볼 것
짧은 질문 ctx 4K, 1슬롯 기본 로딩과 생성 속도
긴 문서 ctx 8K 이상 KV 캐시 증가와 메모리 압박
동시 요청 같은 모델·프롬프트 슬롯별 지연과 OOM 여부

이 기록에는 모델 파일, 양자화 형식, -c, -ngl, 슬롯 수, 운영체제와 GPU 메모리를 함께 적어요. 공식 문서가 특정 하드웨어의 보편적인 토큰 속도를 보장하지 않으므로, 숫자가 필요하면 자신의 모델과 입력으로 측정해야 해요.

되돌릴 때는 컨텍스트부터 줄여요

메모리 부족이 생기면 모델을 바꾸기 전에 동시 슬롯을 줄이고, ctx-size를 낮추고, 필요하면 -ngl을 낮춰 CPU 혼합 실행으로 돌아가요. 반대로 속도가 너무 느리면 컨텍스트를 줄인 상태에서 GPU 레이어를 조금씩 올려요. 한 번에 여러 옵션을 바꾸면 원인을 잃어요.

결국 로컬 LLM의 메모리 계산은 “모델 파일이 VRAM에 들어가는가”에서 끝나지 않아요. 실제 작업의 문맥 길이와 동시 사용자 수를 정한 뒤 KV 캐시와 실행 버퍼에 여유를 남겨야 안정적으로 쓸 수 있어요.

Sources

함께 읽을 글