Llama-Server 라우터 모드 - 재시작 없는 동적 모델 전환

재시작 없이 LLM을 서빙하고 교체합니다.

Page content

llama.cpp는 오랫동안 치명적인 한계점을 가지고 있었습니다. 바로 프로세스당 하나의 모델만 서빙할 수 있었고, 모델 전환을 하려면 프로세스를 재시작해야 했기 때문입니다.

그 시대는 끝났습니다.

최근 업데이트에서 llama-server에 **라우터 모드(Router mode)**가 도입되었는데, 이는 모던한 로컬 LLM 런타임에서 기대하는 것(동적 모델 로드, 요청별 전환 등)에 훨씬 더 가까운 기능을 제공합니다:

  • 동적 모델 로드
  • 필요 시 언로드
  • 요청별 모델 전환
  • 프로세스 재시작 불필요

llm router on the table

즉, 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을 위한 요청이 도달하면:

  1. llama3가 VRAM에서 언로드됨
  2. qwen 가중치가 디스크에서 읽혀서 VRAM으로 로드됨
  3. 추론 실행
  4. 다음 요청에 따라 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와 달리:

  • 자동 모델 추방 전략이 없음
  • 백그라운드 프리-워밍이 없음
  • 자주 사용되는 모델을 위한 우선순위 큐가 없음

llama3mistral 요청을 교대로 보내면, 모든 요청마다 리로드가 트리거됩니다. 이는 메탈(하드웨어)에 더 가까이 붙어 있는 것의 근본적인 비용입니다.

혼합 워크로드에서 지연 시간은 예측할 수 없음

일관되게 하나의 모델을 사용하는 잘 동작하는 워크로드는 빠를 것입니다. 여러 모델을 번갈아 사용하는 워크로드는 느릴 것입니다. 클라이언트 라우팅 로직을 이에 따라 계획하십시오 — 가능한 한 요청을 모델별로 그룹화하세요.

설정이 불안정함

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와 유사한 동작을 얻게 됩니다.

구독하기

시스템, 인프라, AI 엔지니어링에 관한 새 글을 받아보세요.