Llama-Server 라우터 모드 - 재시작 없는 동적 모델 전환
재시작 없이 LLM을 서빙하고 교체합니다.
llama.cpp는 오랫동안 치명적인 한계점을 가지고 있었습니다. 바로 프로세스당 하나의 모델만 서빙할 수 있었고, 모델 전환을 하려면 프로세스를 재시작해야 했기 때문입니다.
그 시대는 끝났습니다.
최근 업데이트에서 llama-server에 **라우터 모드(Router mode)**가 도입되었는데, 이는 모던한 로컬 LLM 런타임에서 기대하는 것(동적 모델 로드, 요청별 전환 등)에 훨씬 더 가까운 기능을 제공합니다:
- 동적 모델 로드
- 필요 시 언로드
- 요청별 모델 전환
- 프로세스 재시작 불필요

즉, Ollama와 유사한 동작이지만, 보조바퀴 없이 더 자유로운 경험을 제공한다는 뜻입니다.
로컬 런타임, 클라우드 API, 그리고 셀프호스팅 인프라 사이에서 아직 고민 중이시라면, LLM 호스팅 개요가 좋은 출발점이 될 것입니다.
사전 요구 사항
라우터 모드는 비교적 새로운 llama-server 빌드가 필요합니다 — 대략 2024년 중반 이후 버전입니다. 구버전 빌드에는 --models-preset 또는 --models-dir 플래그가 없습니다.
설치 옵션(패키지 매니저, 프리빌트 바이너리, 또는 CUDA 지원 전체 소스 빌드)에 대해서는 llama.cpp 퀵스타트를 참조하세요.
llama-server를 구했으면, 해당 빌드가 라우터 모드를 지원하는지 확인하십시오:
llama-server --help | grep -i models
--models-preset 또는 --models-dir가 표시되면 문제없습니다. 없다면 더 새로운 빌드로 업데이트하십시오.
제 현재 모델 관련 도움말 출력은 다음과 같습니다:
-cl, --cache-list show list of models in cache
Prefix/Suffix/Middle) as some models prefer this. (default: disabled)
models with dynamic resolution (default: read from model)
models with dynamic resolution (default: read from model)
embedding models (default: disabled)
--models-dir PATH directory containing models for the router server (default: disabled)
(env: LLAMA_ARG_MODELS_DIR)
--models-preset PATH path to INI file containing model presets for the router server
(env: LLAMA_ARG_MODELS_PRESET)
--models-max N for router server, maximum number of models to load simultaneously
(env: LLAMA_ARG_MODELS_MAX)
--models-autoload, --no-models-autoload
for router server, whether to automatically load models (default:
(env: LLAMA_ARG_MODELS_AUTOLOAD)
라우터 모드가 실제로 하는 일
라우터 모드는 llama-server를 모델 디스패처로 만듭니다.
-m으로 단일 모델에 바인딩하는 대신, 서버는 다음과 같이 동작합니다:
- 모델이 로드되지 않은 상태로 시작
- 특정 모델을 명시한 요청 수신
- 메모리에 없다면 해당 모델 로드
- 추론 실행
- 응답 후 모델 언로드 또는 다음 요청을 위해 워밍 상태 유지
핵심 아이디어
이제는 더 이상 다음을 실행하지 않습니다:
./llama-server -m model.gguf
다음처럼 실행합니다:
./llama-server --models-preset models.ini --port 8080
그리고 클라이언트가 실제로 요청하는 내용에 따라 서버가 무엇을 로드하고 언제 할지 결정하게 합니다.
이것이 중요한 이유는, 하나의 영속적인 프로세스가 전체 모델 플릿(Fleet)을 서빙할 수 있고, 클라이언트가 작업별(코딩 모델, 채팅 모델, 요약 모델 등)로 적절한 모델을 선택할 수 있기 때문입니다. 이 과정에서 사용자 측의 조정 오버헤드가 없습니다.
설정: 모델 정의하기
여기가 여전히 좀 더듬더듬(Raw)한 부분입니다.
아직 완전히 안정적인 공식 형식은 없지만, 현재 빌드들은 설정 파일을 통한 INI 스타일 모델 정의를 지원합니다.
models.ini 예제
[llama3]
model = /opt/models/llama-3-8b-instruct.Q5_K_M.gguf
ctx-size = 8192
ngl = 35
threads = 8
[mistral]
model = /opt/models/mistral-7b-instruct-v0.3.Q4_K_M.gguf
ctx-size = 4096
ngl = 20
threads = 8
[qwen]
model = /opt/models/qwen2.5-coder-7b-instruct.Q5_K_M.gguf
ctx-size = 16384
ngl = 35
threads = 8
각 섹션 이름은 클라이언트가 API 요청의 "model" 필드에서 사용하는 모델 식별자가 됩니다.
주요 설정 매개변수
| 매개변수 | 제어 사항 |
|---|---|
model |
GGUF 파일의 절대 경로 |
ctx-size |
토큰 단위의 컨텍스트 윈도우 크기. 값이 클수록 VRAM 사용량이 증가합니다. |
ngl |
GPU로 오프로드되는 레이어 수. CPU 전용으로 설정하려면 0으로 지정하고, VRAM 한계에 이를 때까지 증가시킵니다. |
threads |
CPU에 남아있는 레이어를 위한 CPU 스레드 수. |
적절한 ngl 값을 선택하는 것은 GPU의 사용 가능한 VRAM에 따라 달라집니다 — GPU 선택 및 하드웨어 경제성에 대해서는 컴퓨트 하드웨어 가이드가 유용한 참고자료입니다. 조정 과정에서 라이브 VRAM 소비량을 모니터링하려면, Linux용 GPU 모니터링 도구를 참조하십시오.
설정과 함께 서버 시작
./llama-server --models-preset /opt/llama.cpp/models.ini --port 8080
서버가 정상적으로 시작되었는지 확인합니다:
curl http://localhost:8080/v1/models | jq '.data[].id'
models.ini의 각 섹션 이름이 모델 ID로 나열되어 보여야 합니다.
안정성에 대한 주석
INI 설정 인터페이스는 아직 발전 중입니다:
- 플래그가 커밋마다 변경될 수 있음
- 일부 매개변수는 특정 빌드 설정에서만 인식됨
- 문서가 구현보다 뒤처져 있음
재시작 간 재현성을 보장해야한다면 특정 llama.cpp 커밋을 고정(Pin)하십시오.
API 사용: 요청 시 모델 전환
서버가 실행 중이라면, 모델 전환은 표준 OpenAI 호환 API를 통해 수행됩니다. 단순히 "model" 필드를 설정하면 됩니다.
등록된 모델 목록 조회
curl http://localhost:8080/v1/models
Completion 요청 — 첫 번째 모델
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"messages": [
{"role": "user", "content": "Explain router mode in one paragraph"}
]
}'
다른 모델로 전환 — 동일한 엔드포인트, 동일한 포트
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen",
"messages": [
{"role": "user", "content": "Write a Python function that reads a CSV file"}
]
}'
서버는 언로드/로드 사이클을 투명하게 처리합니다. 클라이언트 코드는 변경되지 않으며 — model 필드만 변경됩니다.
Python 예제
openai Python 클라이언트를 사용하고 있다면:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8080/v1", api_key="not-needed")
# 코딩 모델 사용
response = client.chat.completions.create(
model="qwen",
messages=[{"role": "user", "content": "Write a Go HTTP handler"}],
)
print(response.choices[0].message.content)
# 채팅 모델로 전환 — 동일한 클라이언트, 다른 모델 이름
response = client.chat.completions.create(
model="llama3",
messages=[{"role": "user", "content": "What is the capital of Australia?"}],
)
print(response.choices[0].message.content)
내부적으로 일어나는 일
llama3가 현재 로드된 상태에서 qwen을 위한 요청이 도달하면:
llama3가 VRAM에서 언로드됨qwen가중치가 디스크에서 읽혀서 VRAM으로 로드됨- 추론 실행
- 다음 요청에 따라
qwen을 로드 상태로 유지하거나 다시 스왑함
이는 일반적인 질문에 대한 직접적인 답변이 됩니다:
로컬 LLM 서버는 재시작 없이 모델을 어떻게 전환할 수 있는가
시작 시점에 바인딩하는 것이 아니라, 요청별로 모델을 동적으로 로드하기 때문입니다.
Systemd 서비스: 프로덕션 리디 서포트
전용 사용자 및 디렉터리 생성
sudo useradd --system --shell /usr/sbin/nologin --home-dir /opt/llama.cpp llm
sudo mkdir -p /opt/llama.cpp/models
sudo chown -R llm:llm /opt/llama.cpp
바이너리와 모델 설정을 해당 위치에 복사합니다:
sudo cp build/bin/llama-server /opt/llama.cpp/
sudo cp models.ini /opt/llama.cpp/
/etc/systemd/system/llama-server.service
[Unit]
Description=Llama.cpp Router Server
After=network.target
[Service]
Type=simple
User=llm
WorkingDirectory=/opt/llama.cpp
ExecStart=/opt/llama.cpp/llama-server --models-preset /opt/llama.cpp/models.ini --port 8080
Restart=always
RestartSec=5
Environment=LLAMA_LOG_LEVEL=info
[Install]
WantedBy=multi-user.target
활성화 및 시작
sudo systemctl daemon-reload
sudo systemctl enable llama-server
sudo systemctl start llama-server
검증 및 로그 확인
sudo systemctl status llama-server
journalctl -u llama-server -f
성공적으로 시작되면 서버가 리스닝 중이고 모델 레지스트리가 로드되었음을 나타내는 로그 줄을 볼 수 있습니다. 빠른 무결성 체크를 위해:
curl -s http://localhost:8080/v1/models | jq '.data[].id'
이제 자동 재시작과 중앙 집중식 모델 전환이 포함된 영속적 서비스를 갖추게 되었습니다 — 수동 프로세스 관리가 필요하지 않습니다. 동일한 패턴을 다른 바이너리에 적용하고 싶다면, Linux에서 실행 파일을 서비스로 호스팅하기를 참고하여 일반적인 접근 방식을 살펴보세요.
llama-server의 --metrics 플래그는 Prometheus 호환 엔드포인트를 노출합니다. llama.cpp 전용 대시보드, PromQL 쿼리 및 알림 규칙에 대해서는 LLM 추론 모니터링 가이드를 참조하십시오. 더 광범위한 옵저버빌리티 설정에 대해서는 옵저버빌리티 가이드가 전체 스택을 다룹니다.
이해해야 할 제한 사항
라우터 모드는 실제로 유용하지만, 프로덕션 환경에서 의존하기 전에 명확히 이해해야 할 트레이드오프가 있습니다.
동시에 메모리에 있는 모델은 하나뿐
models.ini에 여러 모델이 정의되어 있을지라도, 각 워커당 주어진 순간에 VRAM에 상주하는 모델은 하나뿐입니다. 전환은 전체 언로드-리로드 사이클을 의미합니다.
- 전환은 리로드를 의미함
- 지연 시간 급증은 불가피함
- 일반적인 7B 모델의 Q5 퀀트화 기준으로, 디스크 속도와 VRAM 대역폭에 따라 리로드에 3~10초가 걸릴 수 있음
이는 또 다른 중요한 질문에 대한 답변이 됩니다:
llama.cpp는 동시에 여러 모델 서빙을 지원하는가
별로 그렇지 않습니다. 이는 **여러 정의(multiple definitions)**를 지원하지만, 동시 상주(simultaneous residency)는 지원하지 않습니다. 두 모델을 실제로 병렬로 로드해야 한다면, 두 개의 별도 GPU에 두 개의 프로세스가 필요합니다.
모델 크기별 VRAM 소비량과 초당 토큰 수를 측정한 값은 LLM 성능 벤치마크에서 전체적인 그림을 볼 수 있습니다. 16 GB GPU에서의 llama.cpp 특정 수치 — 여러 컨텍스트 크기의 Dense 및 MoE 모델 — 에 대해서는 16 GB VRAM llama.cpp 벤치마크를 참조하십시오.
스마트 캐싱이 없음
최근성에 기반하여 모델을 추방하는 웜풀(warm pool)을 유지하는 Ollama와 달리:
- 자동 모델 추방 전략이 없음
- 백그라운드 프리-워밍이 없음
- 자주 사용되는 모델을 위한 우선순위 큐가 없음
llama3와 mistral 요청을 교대로 보내면, 모든 요청마다 리로드가 트리거됩니다. 이는 메탈(하드웨어)에 더 가까이 붙어 있는 것의 근본적인 비용입니다.
혼합 워크로드에서 지연 시간은 예측할 수 없음
일관되게 하나의 모델을 사용하는 잘 동작하는 워크로드는 빠를 것입니다. 여러 모델을 번갈아 사용하는 워크로드는 느릴 것입니다. 클라이언트 라우팅 로직을 이에 따라 계획하십시오 — 가능한 한 요청을 모델별로 그룹화하세요.
설정이 불안정함
INI 지원은 존재하며 대부분의 최신 빌드에서 작동하지만, 완전히 표준화되어 있지 않습니다. 버전 간에 플래그와 매개변수 이름이 변경되었습니다. llama-server를 업그레이드하면 배포 전에 models.ini가 새로운 빌드와 호환되는지 테스트하십시오.
Llama.cpp vs Ollama
라우터 모드는 Ollama와의 기존 라이프사이클 격차를 줄였습니다 — 동적 로딩과 요청별 전환이 이제 llama-server에 네이티브로 존재합니다 — 하지만 완전히 해소하지는 못했습니다. 메모리 관리가 여전히 기본적이며(추방 정책 없음, 웜풀 없음), 설정 안정성은 실험 단계이며, 두 개의 다른 모델 간 전환은 항상 Ollama의 TTL 기반 킵얼라이브 대신 전체 언로드-리로드 비용을 지불합니다. 간결히 말하면: 라우터 모드는 최대의 제어권과 해킹 가능한 기반을 제공하고, Ollama는 설정할 것이 적은 더 다듬어진, 의견이 분명한(의견적/opinionated) 경험을 제공합니다.
설치, 모델 관리, GPU 배치, KV 캐시 제어, API, 성능, 실패 모드, 그리고 하나를 선택하거나 이기(이동)할 구체적인 트리거에 대한 완전한 1:1 분석은 — 이 사이트의 두 런타임 간의 정통적인 비교인 2026년 llama.cpp vs Ollama를 참조하세요.
Ollama를 선택한다면, Ollama CLI 치트시트가 일상적인 명령어를 다룹니다. vLLM, LM Studio, LocalAI도 포함하는 더 광범위한 비교를 보고 싶다면, 2026년 다양한 로컬 런타임 비교를 참조하십시오.
Llama.cpp vs llama-swap
llama-swap는 하나 이상의 llama-server 인스턴스 앞에 위치하는 외부 오케스트레이터입니다:
- 요청을 가로채
model필드를 검사 - 해당 모델을 위한 적절한
llama-server프로세스 시작 - 구성 가능한 시간 초과 후에 유휴 인스턴스 종료
- 모델이 준비되면 요청을 프록시
수동으로 설정하는 방법에 대해서는 llama-swap 퀵스타트를 참조하세요.
주요 차이점
| 관점 | 라우터 모드 | llama-swap |
|---|---|---|
| 내장 여부 | 예 | 아니오 (별도 바이너리) |
| 성숙도 | 실험 단계 | 더 안정적 |
| 유연성 | 제한적 | 높음 |
| 제어 레이어 | 내부 | 외부 프록시 |
| 모델별 설정 | INI 파일 | YAML 파일 |
| 프로세스 모델 | 단일 프로세스 | 모델당 프로세스 하나 |
llama-swap을 사용할 때
llama-swap은 모델별로 프로세스 수준의 격리를 제공하므로, 한 모델 인스턴스의 크래시가 다른 인스턴스에 영향을 주지 않습니다. 또한 각 모델이 완전히 독립적인 llama-server 플래그로 실행되도록 허용합니다.
다음과 같은 경우 사용하십시오:
- 더 나은 라이프사이클 제어와 격리 필요
- 구성 가능한 유휴 시간 초과를 가진 더 스마트한 전환 로직 필요
- 더 예측 가능한 지연 시간 (첫 번째 로드 후 각 모델이 웜 프로세스를 가짐)
- 언젠가가 아니라 오늘 당장 프로덕션 안정성 필요
네이티브 라우터 모드로 충분한 경우
다음과 같은 경우 내장 라우터를 사용하십시오:
- 외부 의존성 제로
- 관리할 단일 프로세스
- 더 단순한 배포 (바이너리 하나, 설정 파일 하나)
- 개발 또는 단일 사용자 설정을 위한 최소 스택
최종 의견
라우터 모드는 llama-server에 있어 의미 있는 진보입니다.
그것은 오랫동안 지속되었던 수요에 대한 답변입니다:
llama.cpp 서버의 라우터 모드가 무엇인가
이것은 정적인 바이너리를 동적 추론 서비스로 바꾸는 누락된 레이어입니다 — 한 프로세스가 모델 카탈로그 전체에 대한 요청을 처리할 수 있게 됩니다.
하지만 아직 완성되지 않았습니다.
오늘날 이것은:
- 실제 워크로드에 충분히 강력함
- 더 정교한 라우팅의 기반으로서 유망함
- 설정과 안정성의 가장자리는 약간 거친 상태
워크로드가 예측 가능하며 요청을 모델별로 그룹화할 수 있다면, 라우터 모드는 오늘 당장 잘 작동합니다. 프로덕션급 신뢰성과 모델별 격리가 필요하면, 네이티브 구현이 성숙할 때까지 llama-swap을 선택하십시오.
재시작 없이 VRAM을 해제해야 할 때 — 벤치마크 실행, 유지보수 윈도우, 또는 깔끔한 개발 리셋을 위해 — 스크립트 가능한 접근 방식은 로드된 모델 목록을 조회하고 각 모델에 대해 언로드 엔드포인트를 호출하는 것입니다. 전체 curl 및 jq 패턴은 재시작 없이 llama.cpp 라우터 모델 모두 언로드하기에서 다룹니다.
어떤 경우이든, 당신은 기계를 숨기지 않고 Ollama와 유사한 동작을 얻게 됩니다.