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

리스타트 없이 LLM을 배포하고 교체하세요.

Page content

오랜 기간 동안 llama.cpp에는 뚜렷한 한계가 존재했습니다.
즉, 프로세스당 단 하나의 모델만 서빙(serving)할 수 있었으며, 모델을 변경하려면 재시작이 필요했습니다.

그 시기는 끝났습니다.

최근 업데이트로 llama-server에 **라우터 모드(Router mode)**가 도입되었으며, 이는 현대적인 로컬 LLM 런타임에서 사람들이 기대하는 기능에 훨씬 더 가까운 것을 제공합니다:

  • 동적 모델 로딩
  • 요청에 따른 언로딩
  • 요청별 모델 전환
  • 프로세스 재시작 없음

llm router on the table

즉, 훈련용 보조 바퀴(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가 로드된 경우:

  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 추론 모니터링 가이드를 참조하세요. 더 광범위한 관측성(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)이 없습니다
  • 자주 사용되는 모델을 위한 우선순위 큐가 없습니다

llama3mistral에 번갈아가며 요청을 보내면, 모든 단일 요청이 재로딩을 트리거합니다. 이는 메탈(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 라우터 모델 언로딩에 다루어집니다.

어떤 경우든, 기계 장치를 숨기지 않으면서 올라마와 유사한 동작을 얻게 됩니다.

구독하기

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