Llama-Server 라우터 모드 - 재시작 없이 동적 모델 전환
리스타트 없이 LLM을 배포하고 교체하세요.
오랜 기간 동안 llama.cpp에는 뚜렷한 한계가 존재했습니다.
즉, 프로세스당 단 하나의 모델만 서빙(serving)할 수 있었으며, 모델을 변경하려면 재시작이 필요했습니다.
그 시기는 끝났습니다.
최근 업데이트로 llama-server에 **라우터 모드(Router mode)**가 도입되었으며, 이는 현대적인 로컬 LLM 런타임에서 사람들이 기대하는 기능에 훨씬 더 가까운 것을 제공합니다:
- 동적 모델 로딩
- 요청에 따른 언로딩
- 요청별 모델 전환
- 프로세스 재시작 없음

즉, 훈련용 보조 바퀴(training wheels) 없이 올라마(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를 **모델 디스패처(Model Dispatcher)**로 전환합니다.
-m을 통해 단일 모델에 바인딩하는 대신, 서버는 다음과 같이 동작합니다:
- 모델이 로드되지 않은 상태로 시작
- 모델 이름을 지정한 요청을 받음
- 메모리에 이미 로드되어 있지 않다면 해당 모델을 로드
- 추론 실행
- 응답 후 모델을 선택적으로 언로딩하거나, 다음 요청을 위해 온열(warm) 상태로 유지
핵심 아이디어
이제 더 이상 다음과 같이 실행하지 않습니다:
./llama-server -m model.gguf
다음과 같이 실행합니다:
./llama-server --models-preset models.ini --port 8080
그리고 서버가 클라이언트가 실제로 요청한 내용에 따라 무엇을 로드할지, 언제 로드할지 결정하도록 맡기는 것입니다.
이는 하나의 지속적 프로세스가 전체 모델 군(fleet)을 서빙할 수 있음을 의미하며, 클라이언트는 작업별로 적절한 모델(코딩 모델, 채팅 모델, 요약 모델 등)을 선택할 수 있어, 사용자 측에서 조정 오버헤드가 전혀 없습니다.
설정: 모델 정의
여기서 상황이 아직 다소 원시적입니다.
완전히 안정적인 공식 포맷은 아직 없으나, 현재 빌드는 설정 파일을 통해 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 Identifier)**가 됩니다.
주요 설정 파라미터
| 파라미터 | 제어 대상 |
|---|---|
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
완료 요청 — 첫 번째 모델
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)
내부적으로 일어나는 일
qwen에 대한 요청이 도착하고 현재 llama3가 로드된 경우:
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 추론 모니터링 가이드를 참조하세요. 더 광범위한 관측성(observability) 설정에 대해서는 관측성 가이드가 전체 스택을 다룹니다.
이해해야 할 한계점
라우터 모드는 진정으로 유용하지만, 프로덕션 환경에 의존하기 전에 명확히 알아두어야 할 트레이드오프가 존재합니다.
한 번에 메모리에 하나의 모델만 존재
models.ini에 여러 모델이 정의되어 있음에도 불구하고, 어떤 주어진 순간에도 워커당 VRAM에 상주하는 모델은 하나뿐입니다. 전환은 완전한 언로딩-재로딩 사이클을 의미합니다.
- 전환은 재로딩을 의미합니다
- 대기시간 급증은 피할 수 없습니다
- 일반적인 7B 모델(Q5 양자화)에서 재로딩은 디스크 속도와 VRAM 대역폭에 따라 3~10초가 소요될 수 있습니다
이는 또 다른 주요 질문에 대한 답변입니다:
llama.cpp는 여러 모델을 동시에 서빙하는 것을 지원하는가
아직 아닙니다. 이는 동시 상주가 아닌 여러 정의를 지원합니다. 두 모델을 진정으로 병렬로 로드해야 한다면, 두 개의 별도 GPU에서 두 개의 프로세스가 필요합니다.
측정된 VRAM 소비량 및 모델 크기별 초당 토큰 수에 대해서는 LLM 성능 벤치마크가 전체 그림을 다룹니다. 16 GB GPU에서 llama.cpp에 특화된 수치 — 다양한 컨텍스트 크기에서의 Dense 및 MoE 모델 — 에 대해서는 16 GB VRAM llama.cpp 벤치마크를 참조하세요.
스마트 캐싱 부재
최근 사용 빈도에 따라 모델을 이출하는 온열 풀(warm pool)을 유지하는 Ollama와 달리:
- 자동 모델 이출 전략이 없습니다
- 백그라운드 사전 온열(pre-warming)이 없습니다
- 자주 사용되는 모델을 위한 우선순위 큐가 없습니다
llama3와 mistral에 번갈아가며 요청을 보내면, 모든 단일 요청이 재로딩을 트리거합니다. 이는 메탈(metal, 하드웨어)에 더 가까이 접근하는 근본적인 비용입니다.
혼합 워크로드의 경우 대기시간이 예측 불가능
하나의 모델을 일관되게 사용하는 잘 동작하는 워크로드는 빠릅니다. 여러 모델을 번갈아 사용하는 워크로드는 느립니다. 클라이언트 라우팅 로직을 이에 따라 계획하세요 — 가능한 한 모델별로 요청을 그룹화하세요.
설정이 안정적이지 않음
INI 지원이 존재하며 대부분의 최신 빌드에서 작동하지만, 완전히 표준화되지 않았습니다. 플래그 및 파라미터 이름이 버전 간에 변경되었습니다. llama-server를 업그레이드하면 배포 전에 새 빌드와 models.ini를 테스트하세요.
Llama.cpp vs Ollama: 솔직한 비교
| 기능 | llama.cpp 라우터 | Ollama |
|---|---|---|
| 동적 로딩 | 예 | 예 |
| 모델 전환 | 예 | 예 |
| 내장 레지스트리 | 부분적 (INI) | 예 (pull 기반) |
| 메모리 관리 | 기본 | 고급 |
| 모델 이출 | 없음 | TTL 기반 |
| UX 완성도 | 낮음 | 높음 |
| OpenAI API 호환 | 예 | 예 |
| 제어 | 최대 | 의견 기반(Opinionated) |
| 설정 안정성 | 실험적 | 안정적 |
의견 기반 관점
다음과 같은 경우 llama.cpp 라우터 모드를 선택하세요:
- 모델별 런타임 파라미터에 대한 최대 제어
- 최소 프로세스 오버헤드
- 추상화 레이어 없이 llama.cpp 플래그에 직접 접근
- 사용자 정의 도구를 위한 해킹 가능한 기반
다음과 같은 경우 Ollama를 선택하세요:
- 안정적이고 다듬어진 경험
- 자동 모델 다운로드 및 버전 관리
- 구성 없이 스마트한 유지(kick-alive) 및 이출
- 첫날부터 배터리 포함(batteries included, 모든 기능 기본 제공)
둘 다 틀린 선택이 아닙니다. 선택은 스스로 관리하려는 정도에 달려 있습니다.
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-and-jq 패턴은 재시작 없이 모든 llama.cpp 라우터 모델 언로딩에 다루어집니다.
어떤 경우든, 기계 장치를 숨기지 않으면서 올라마와 유사한 동작을 얻게 됩니다.