오픈소스 LLM을 직접 실행하려고 찾아보다 보면 비슷해 보이는 도구들을 계속 만나게 된다.
로컬에서 모델을 실행하려고 하면 Ollama가 나오고, LLM API 서버를 구축하려고 하면 vLLM이 등장한다. DeepSeek-R1처럼 수백B 규모의 초거대 모델까지 관심을 넓히면 이번에는 KTransformers라는 이름이 보인다.
처음에는 셋 다 비슷해 보인다.
결국 모델 파일을 메모리에 올리고 GPU로 추론하는 프로그램 아닌가?
큰 범위에서 보면 맞다.
하지만 실제로는 세 도구가 해결하려는 병목이 다르다.
| 상황 | 먼저 볼 도구 | 해결하려는 문제 |
|---|---|---|
| 내 PC에서 모델을 빠르게 실행하고 싶다 | Ollama | 설치와 실행의 복잡성 |
| 여러 사용자에게 LLM API를 제공하고 싶다 | vLLM | GPU 메모리와 처리량 |
| 모델이 VRAM에 들어가지 않는다 | KTransformers | 초거대 모델의 메모리 배치 |
한 줄로 요약하자면,
로컬은 Ollama, 서버는 vLLM, 괴물 모델은 KTransformers.
물론 절대적인 규칙은 아니다.
Ollama에도 API가 있어 서버처럼 사용할 수 있고, vLLM 역시 개인 장비에서 실행할 수 있다. KTransformers도 API 서버와 동시 요청 기능을 지원한다. 따라서 중요한 질문은 “어떤 프로그램이 더 좋은가?”가 아니다.
지금 내 LLM 환경에서 가장 먼저 해결해야 할 병목이 무엇인가?
이 기준으로 보면 세 도구의 차이가 훨씬 선명해진다.
Ollama는 모델보다 실행 환경과 싸우는 문제를 줄인다
처음 오픈소스 LLM을 직접 실행할 때는 모델 성능을 확인하기도 전에 환경 설정부터 문제가 되는 경우가 많다.
Python 설치 ➡ PyTorch 설치 ➡ CUDA 버전 확인 ➡ Transformers 설치
➡ 모델 파일 다운로드 ➡ 양자화 형식 확인 ➡ GPU 메모리가 부족하면 설정 변경
그러다 모델에게 질문 한 번 해보기도 전에 이런 오류를 마주친다.
PyTorch CUDA version: 13.0
TorchAudio CUDA version: 12.8
LLM을 테스트하려던 것이지 CUDA 의존성과 싸우려던 것은 아니다.
Ollama가 편한 이유가 바로 여기에 있다.
ollama run llama3.2
사용자는 모델을 선택하고 실행하면 된다.
필요한 모델을 준비하고 추론 환경을 구성하는 상당 부분은 Ollama가 대신 처리한다.
즉 Ollama가 먼저 줄여주는 것은 GPU 사용량이 아니라 개발자가 모델을 실제로 실행하기까지 겪는 번거로움이다.
새로운 모델을 확인할 때 중요한 것은 일단 실행되는 것이다
새로운 모델이 공개됐다고 생각해보자.
궁금한 것은 보통 이런 것들이다.
- 한국어 답변이 자연스러운가?
- 코딩을 얼마나 잘하는가?
- 원하는 JSON 형식을 제대로 지키는가?
- 내 프롬프트에서는 기존 모델보다 결과가 좋은가?
- 내 장비에서 어느 정도 속도가 나오는가?
이 단계에서는 초당 처리량을 극단적으로 최적화하는 것이 우선순위가 아니다.
모델을 빠르게 바꿔가며 실제 결과를 확인하는 것이 먼저다.
새 모델 발견 ➡ Ollama ➡ 모델 실행 ➡ 프롬프트 테스트 ➡ 사용 가능성 판단
Ollama는 이런 개발 흐름과 잘 맞는다.
설치 후에는 로컬 API도 제공하기 때문에 단순히 터미널에서 모델과 대화하는 것을 넘어 애플리케이션과 연결해 사용할 수도 있다.
따라서 Ollama를 단순히 “터미널에서 LLM과 채팅하는 프로그램”으로만 보면 범위를 너무 좁게 보는 것이다.
다만 Ollama의 강점이 가장 잘 드러나는 지점은 개발자가 모델을 가져와 빠르게 실행할 수 있게 만드는 경험이다.
현재 Ollama는 로컬 모델뿐 아니라 클라우드 모델을 사용하는 기능도 제공한다. 하지만 이 글에서는 세 도구의 차이를 명확하게 설명하기 위해 대표적인 사용 사례인 로컬 실행을 기준으로 살펴본다.
사용자가 늘어나면 모델 실행보다 GPU 활용률이 중요해진다
로컬에서 모델을 테스트했다.
결과가 괜찮아서 실제 서비스에 적용하기로 했다.
개발 단계에서는 요청이 하나뿐이다.
사용자 ➡ LLM ➡ GPU
이 정도에서는 큰 문제가 없다.
하지만 서비스를 공개하고 사용자가 늘어나면 상황이 달라진다.
사용자 A ─┐
사용자 B ─┤
사용자 C ─┤
사용자 D ─┤
사용자 E ─┤
↓
LLM Server
↓
GPU
이제 질문은 더 이상 모델이 실행되는가? 가 아닌
동시에 몇 개의 요청을 처리할 수 있는가?
요청이 계속 들어올 때 GPU를 충분히 활용하고 있는가?
같은 GPU 한 장으로 일정 시간 동안 얼마나 많은 토큰을 처리할 수 있는가?
여기서 vLLM을 볼 이유가 생긴다.
vLLM은 단순히 LLM을 실행하는 것을 넘어 높은 처리량으로 모델을 서빙하는 것에 초점을 둔 inference engine이다.
OpenAI 호환 API 서버도 제공하기 때문에 애플리케이션에서는 일반적인 LLM API와 비슷한 형태로 연결할 수 있다.
Application ➡ OpenAI-compatible API ➡ vLLM ➡ GPU
하지만 API 형식 자체가 vLLM의 본질은 아니다.
중요한 것은 그 아래에서 여러 요청을 어떻게 스케줄링하고, GPU 메모리를 어떻게 활용하느냐다.
vLLM은 들어오는 요청을 계속 다시 묶는다
LLM 요청의 길이는 일정하지 않다.
세 명이 동시에 요청했다고 가정해보자.
A █████████████████
B ██████
C ███████████
B는 다른 요청보다 먼저 끝난다.
처음 세 요청을 하나의 고정된 batch처럼 묶어 처리한다면 B가 끝난 뒤 생긴 자원을 효율적으로 활용하기 어렵다.
하지만 실제 서버에는 새로운 요청이 계속 들어온다.
A █████████████████
B ██████
D ███████████
C ███████████
E ███████
B가 끝나면 D를 넣고, C가 끝나면 E를 처리하기 시작하는 식으로 GPU가 실행할 작업을 계속 다시 구성하는 편이 효율적이다.
이런 방향의 핵심 기술이 continuous batching이다. 처음 묶인 요청이 모두 끝날 때까지 기다리는 대신, 실행 중인 요청의 상태에 따라 새로운 요청을 계속 스케줄링한다. 서비스 환경에서는 이 차이가 중요하다.
사용자 한 명에게 답변을 얼마나 빨리 생성하는지만 보는 것이 아니라, GPU 전체가 일정 시간 동안 얼마나 많은 토큰과 요청을 처리할 수 있는지를 봐야 하기 때문이다.
PagedAttention은 다른 문제를 해결한다
vLLM을 찾아보면 PagedAttention이라는 이름도 자주 등장한다.
continuous batching과 함께 언급되는 경우가 많지만 두 기술이 해결하는 문제는 다르다.
continuous batching이 어떤 요청을 언제 실행할 것인가에 가깝다면, PagedAttention은 KV Cache를 GPU 메모리에 어떻게 배치하고 관리할 것인가에 가깝다.
KV Cache가 커지면 VRAM은 모델 가중치만의 문제가 아니다
LLM은 한 번에 답변 전체를 만드는 것이 아니라 토큰을 하나씩 생성한다.
이때 매번 이전 토큰 전체에 대한 Attention 계산을 처음부터 반복하면 비용이 너무 크다. 그래서 이전 계산에서 만들어진 Key와 Value를 저장해두고 다음 토큰을 생성할 때 다시 사용한다.
이 저장 공간이 KV Cache다.
Prompt ➡ Token 생성 ➡ KV Cache 저장 ➡ 다음 Token 생성 ➡ 기존 KV Cache 재사용
사용자가 한 명일 때는 크게 체감하지 못할 수도 있다.
하지만 동시 요청이 많아지고 context가 길어질수록 KV Cache가 사용하는 VRAM도 커진다.
문제는 요청의 길이가 모두 다르다는 것이다.
요청 A: 500 tokens
요청 B: 4,000 tokens
요청 C: 12,000 tokens
요청 D: 2,000 tokens
모든 요청에 큰 연속 메모리 공간을 미리 확보하는 방식은 메모리 낭비가 발생하기 쉽다.
PagedAttention은 운영체제의 메모리 페이징에서 아이디어를 가져와 KV Cache를 일정한 block 단위로 관리한다.
개념적으로 보면 다음과 같다.
Request A
[Block 1][Block 7][Block 9]
Request B
[Block 2][Block 3][Block 11][Block 14]
한 요청의 KV Cache가 반드시 하나의 거대한 연속 메모리 영역에 배치될 필요가 없어지는 것이다.
이를 통해 메모리 낭비를 줄이고 같은 GPU 메모리 안에서 더 많은 요청을 처리할 여지를 확보할 수 있다.
두 기술의 역할을 정리하면 다음과 같다.
Continuous Batching
→ 실행할 요청을 효율적으로 스케줄링
PagedAttention
→ 요청이 사용하는 KV Cache를 효율적으로 관리
둘 다 결과적으로 서버의 처리량을 높이는 데 기여하지만, 해결하는 문제는 서로 다르다.
서버에서는 tokens/sec 하나만 보면 부족하다
로컬에서 모델을 테스트할 때는 흔히 이런 숫자를 본다.
72 tokens/sec
한 요청의 답변이 얼마나 빠르게 생성되는지 확인할 때는 유용하다.
하지만 실제 서비스를 운영하려면 봐야 할 지표가 늘어난다.
TTFT
Time To First Token.
사용자가 요청을 보낸 뒤 첫 번째 토큰이 출력될 때까지 걸리는 시간이다.
특히 스트리밍 응답에서는 사용자가 느끼는 체감 속도에 큰 영향을 준다.
ITL
Inter-Token Latency.
첫 번째 토큰 이후 다음 토큰들이 어느 정도 간격으로 생성되는지를 나타낸다.
Throughput
일정 시간 동안 시스템 전체가 얼마나 많은 토큰이나 요청을 처리할 수 있는지를 나타낸다.
예를 들어 한 사용자에게 100 tokens/sec를 제공하는 서버보다, 개별 사용자의 생성 속도는 조금 느리더라도 여러 요청을 동시에 처리해 시스템 전체로 1,000 tokens/sec를 처리하는 서버가 실제 서비스에서는 더 가치 있을 수 있다.
그래서 LLM 서버의 비용은 단순히 GPU 가격으로 결정되지 않는다.
GPU 비용
↓
같은 시간 동안 처리 가능한 요청 / 토큰
↓
실제 요청당 비용
비싼 GPU라도 한 장으로 훨씬 많은 요청을 처리할 수 있다면 결과적으로 요청당 비용은 더 낮아질 수 있다.
반대로 GPU 한 장의 가격이 저렴하더라도 처리량이 낮아 여러 장이 필요하다면 전체 비용은 오히려 높아진다.
vLLM을 쓰는 이유는 단순히 모델을 실행하기 위해서가 아니라, 제한된 하드웨어에서 더 많은 실제 요청을 처리하기 위해서다.
그런데 모델 자체가 VRAM보다 크면 문제가 다시 바뀐다
여기까지는 한 가지 전제가 있었다.
모델 가중치를 어떻게든 GPU 메모리에 올릴 수 있다는 것이다. 하지만 DeepSeek-R1 같은 초거대 모델에서는 이 전제부터 깨진다. DeepSeek-R1은 총 671B parameters 규모의 MoE 모델이다. 671B 모델을 FP16이나 BF16처럼 파라미터당 2byte로 단순 계산하면 모델 가중치만으로도 1TB를 훨씬 넘는다. 양자화를 적용하면 크기를 크게 줄일 수 있지만, 4bit 수준으로 낮춰도 여전히 수백 GB 규모다.
24GB VRAM을 가진 GPU 한 장과 비교하면 차이가 명확하다.
GPU VRAM 24GB VS Model 수백 GB
이 상황에서는 PagedAttention만으로 해결할 수 없다. KV Cache를 최적화하기도 전에 모델 가중치 자체가 VRAM에 들어가지 않기 때문이다. 여기서 KTransformers가 해결하려는 문제가 드러난다.
KTransformers는 모든 것을 GPU에 넣겠다는 전제를 버린다
KTransformers는 heterogeneous LLM inference optimization을 위한 프레임워크다.
핵심적인 접근은 다음과 같다.
모델 전체를 GPU에 넣는 대신 CPU와 GPU에 적절히 나눠서 실행하면 어떨까?
개념적으로 보면 다음과 같다.
LLM
│
┌───┐
↓ ↓
GPU CPU
│ │
VRAM RAM
GPU에서 처리하는 것이 유리한 연산과 데이터는 GPU에 두고, CPU에서도 처리할 수 있는 부분이나 큰 용량을 차지하는 파라미터는 시스템 RAM을 활용한다. 단순히 “GPU 메모리가 부족하니 남는 데이터를 RAM에 넣는다” 정도로 이해하면 부족하다.
어떤 연산과 데이터를 어느 장치에 배치할 것인지 자체가 최적화 대상이다.
MoE 구조가 이런 접근과 잘 맞는 이유
DeepSeek-R1의 구조를 이해하면 KTransformers가 왜 이런 모델과 자주 함께 언급되는지도 알 수 있다.
DeepSeek-R1은 총 671B 파라미터를 가지고 있지만, 모든 파라미터가 매 토큰마다 동시에 사용되는 dense 모델은 아니다.
MoE, 즉 Mixture-of-Experts 구조를 사용하며 한 토큰을 처리할 때 활성화되는 파라미터는 약 37B다.
전체 Expert
████████████████████████████
한 Token에서 활성화
███
그렇다고 671B 가운데 37B만 메모리에 가지고 있으면 된다는 뜻은 아니다.
다음 토큰에서는 다른 expert가 선택될 수 있기 때문에 모델 파라미터 자체는 여전히 저장되어 있어야 한다.
다만 모든 expert가 매 토큰마다 계산되는 것은 아니다. 이 특성을 활용하면 계산 성능이 특히 필요한 부분은 GPU에 배치하고, 큰 용량을 차지하는 expert 관련 데이터를 CPU 메모리 쪽에 배치하는 전략을 사용할 수 있다.
KTransformers가 DeepSeek 계열 MoE 모델에서 CPU와 GPU를 함께 적극적으로 활용하는 이유다.
“RTX 4090 한 장으로 DeepSeek 671B”는 절반만 맞는 말이다
KTransformers를 검색하다 보면 꽤 자극적인 표현을 볼 수 있다.
RTX 4090 한 장으로 DeepSeek-R1 671B 실행
실행할 수 있다는 의미에서는 틀린 표현이 아니다. 하지만 이 문장만 보면 중요한 하드웨어 하나가 빠져 있다. RAM이다.
KTransformers 공식 문서에서 제시하는 DeepSeek-R1 Q4_K_M 구성은 대략 다음 수준이다.
| 항목 | 공식 예시 |
|---|---|
| 모델 크기 | 약 377GB |
| 최소 VRAM | 약 14GB |
| 최소 DRAM | 약 382GB |
| 권장 DRAM | 512GB |
실제 시스템은 다음에 더 가깝다.
24GB급 GPU
+
수백 GB 시스템 RAM
+
충분한 CPU 성능과 메모리 대역폭
↓
DeepSeek-R1 671B Q4_K_M 실행
RTX 4090 한 장을 평범한 게이밍 PC에 꽂는다고 갑자기 671B 모델을 실행할 수 있다는 이야기는 아니다.
KTransformers의 공식 성능 예시에도 Xeon CPU와 수백 GB에서 1TB 수준의 DDR5 메모리를 갖춘 상당히 강력한 시스템이 사용된다. 따라서 “GPU 한 장” 이라는 표현만 보고 실제 하드웨어 요구 사항을 판단해서는 안 된다.
KTransformers는 VRAM을 없애는 기술이 아니다
여기서 또 하나 오해하기 쉬운 부분이 있다. CPU RAM은 VRAM보다 상대적으로 저렴하고 훨씬 큰 용량으로 구성할 수 있다.
그러면 이런 생각이 들 수 있다.
그렇다면 GPU 대신 RAM만 많이 꽂으면 되는 것 아닌가?
그렇지는 않다.
GPU VRAM은 높은 메모리 대역폭을 제공하며 GPU 연산 장치와 매우 가깝다.
반면 시스템 RAM에서 데이터를 가져와 CPU에서 계산하거나 CPU와 GPU 사이에서 데이터를 이동하려면 추가적인 비용이 발생한다. 따라서 heterogeneous inference는
VRAM 부족
↓
RAM 사용
↓
성능 손실 없이 해결
과 같은 마법이 아니다.
정확히는 다음에 가깝다.
GPU에 모델 전체를 올릴 수 없음
↓
CPU / RAM까지 계산 자원으로 활용
↓
실행 가능한 하드웨어 범위를 넓힘
KTransformers의 가치는 원래 내 장비에서는 실행하기 어려웠던 모델을 실행 가능한 영역으로 끌어오는 데 있다.
고성능 GPU 클러스터와 같은 처리량을 더 저렴한 장비에서 그대로 얻는 기술이라고 이해하면 안 된다.
실제 서비스가 목적이라면 더 작은 모델이나 distilled 모델을 사용하는 쪽이 성능과 비용 면에서 훨씬 합리적인 경우도 많다.
671B 모델을 실행할 수 있다는 것과 671B 모델을 실제 서비스에 사용하는 것이 좋은 선택이라는 것은 전혀 다른 문제다.
세 도구는 경쟁 제품이라기보다 최적화 지점이 다르다
이제 처음의 표를 조금 더 구체적으로 확장해볼 수 있다.
| Ollama | vLLM | KTransformers | |
|---|---|---|---|
| 먼저 해결하려는 문제 | 모델 실행의 복잡성 | 다중 요청 처리 효율 | 모델이 VRAM을 넘는 문제 |
| 대표 환경 | 개인 PC, 개발 환경 | LLM API 서버 | 대용량 RAM을 갖춘 CPU/GPU 시스템 |
| 핵심 가치 | 쉬운 모델 실행 | 높은 serving throughput | heterogeneous inference |
| 중요 자원 | GPU/CPU와 사용 편의성 | GPU VRAM과 처리량 | GPU + CPU + 대용량 RAM |
| 대표 관심사 | 빠른 테스트 | batching, KV Cache, concurrency | placement, offloading, MoE |
| 잘못된 기대 | 항상 최고 성능 | 모델 품질까지 높여줌 | 적은 RAM으로 671B 실행 |
중요한 것은 세 도구의 기능이 완전히 분리되어 있는 것은 아니라는 점이다.
- Ollama도 API 서버를 제공한다.
- vLLM도 로컬에서 실행할 수 있다.
- KTransformers도 OpenAI/Ollama 호환 API와 동시 요청 처리 기능을 제공한다.
기능 목록만 놓고 보면 서로 겹치는 부분이 있다. 하지만 각 프로젝트가 가장 먼저 최적화하려는 문제가 다르다.
Ollama "모델 하나 돌려보기가 왜 이렇게 복잡하지?" ➡ 실행 경험 단순화
vLLM "요청이 계속 들어오는데 GPU를 어떻게 더 잘 쓰지?" ➡ Serving 효율 최적화
KTransformers "애초에 모델이 VRAM에 들어가지 않는데?" ➡ CPU + GPU heterogeneous inference
이 관계를 이해하고 나면 Ollama vs vLLM vs KTransformers라는 단순 비교 자체가 조금 어색하다는 것도 알 수 있다.
셋은 같은 문제를 해결하기 위해 만들어진 세 가지 구현체가 아니다.
결국 무엇을 쓰면 될까?
실제 선택은 생각보다 단순하게 시작할 수 있다.
새로운 모델을 내 PC에서 테스트하고 싶다
먼저 Ollama를 보면 된다.
새 모델 발견 ➡ 다운로드와 환경 설정이 번거로움 ➡ Ollama ➡ 빠르게 실행하고 검증
처음부터 최고 수준의 처리량을 가진 서버를 만들 필요는 없다.
우선 모델이 원하는 결과를 내는지 확인하는 것이 먼저다.
실제 사용자가 접속하는 LLM API를 운영한다
이때부터는 vLLM 같은 inference serving engine을 검토할 이유가 생긴다.
사용자 증가 ➡ 동시 요청 증가 ➡ KV Cache 증가 ➡ GPU 사용량 증가 ➡ 요청당 비용 증가
여기서는 단순한 생성 속도만 보면 안 된다.
최소한 다음 지표를 함께 봐야 한다.
- TTFT
- ITL
- Tokens/sec
- Throughput
- VRAM 사용량
- 동시 요청 수
- 요청당 비용
실제 모델과 GPU 조합으로 benchmark한 결과를 바탕으로 판단해야 한다.
vLLM을 사용했다 = 서버가 빠르다는 공식은 없다.
모델 구조, 양자화 방식, context length, 요청 패턴, GPU 종류에 따라 결과는 달라진다.
DeepSeek-R1 671B처럼 모델 자체가 VRAM보다 훨씬 크다
이 경우에는 KTransformers 같은 heterogeneous inference 접근을 검토할 수 있다.
모델 가중치 > 사용 가능한 VRAM ➡ GPU만으로 실행하기 어려움 ➡ CPU + RAM + GPU 활용 ➡ KTransformers
다만 이 단계에서는 GPU 모델명만 봐서는 안 된다.
CPU 성능, RAM 용량, 메모리 채널, 메모리 대역폭, 양자화 방식까지 함께 살펴봐야 한다.
그리고 목적이 연구나 초거대 모델 실험이 아니라 실제 서비스라면 먼저 한 가지를 물어야 한다.
정말 이 크기의 모델이 필요한가?
더 작은 모델이 요구하는 품질을 만족한다면 대부분의 운영 환경에서는 그쪽이 훨씬 현실적인 선택이다.
LLM 실행 도구를 고르는 것은 병목을 고르는 일이다
Ollama, vLLM, KTransformers 중 어떤 것이 가장 좋은지를 묻는 것만으로는 적절한 도구를 고르기 어렵다.
먼저 현재 문제가 무엇인지 봐야 한다.
실행하기가 너무 복잡하다
→ Ollama
동시 요청 때문에 GPU 효율이 문제다
→ vLLM
모델 자체가 VRAM에 들어가지 않는다
→ KTransformers
시스템이 커질수록 문제는 모델의 정확도에서 끝나지 않는다.
같은 모델이라도
- 몇 bit로 양자화했는지,
- VRAM을 얼마나 사용하는지,
- KV Cache가 얼마나 커지는지,
- 어떤 연산을 CPU로 넘기는지,
- 첫 토큰이 얼마나 빨리 나오는지,
- 동시에 몇 명의 요청을 처리할 수 있는지
에 따라 필요한 하드웨어와 실제 서비스 비용이 크게 달라진다.
LLM Runtime을 선택한다는 것은 결국 어떤 모델을 쓸지 정하는 것만이 아니라, 내 시스템에서 어떤 병목을 먼저 해결할지 결정하는 일이다.
