로컬 LLM API 활용

클라우드 API 대신 자체 하드웨어에서 LLM을 실행하면 데이터 프라이버시, 비용 절감, 오프라인 작업이 가능합니다. Ollama, LM Studio, LocalAI, vLLM, Text Generation WebUI 등 주요 로컬 LLM 솔루션의 설치부터 프로덕션 배포까지 완벽 가이드를 제공합니다.

업데이트 안내: 모델/요금/버전/정책 등 시점에 민감한 정보는 변동될 수 있습니다. 최신 내용은 공식 문서를 확인하세요.
핵심 포인트
  • Ollama: 가장 간단한 설치와 사용, CLI 중심, GGUF 모델
  • LM Studio: GUI 기반, 초보자 친화적, 원클릭 모델 다운로드
  • LocalAI: OpenAI 호환 API, 다양한 모델 형식 지원
  • Text Generation WebUI: 고급 설정, 최대 커스터마이징, 확장 풍부
  • vLLM: 프로덕션 최적화, 최고 성능, PagedAttention, GPU 필수
  • 하드웨어 요구사항: 최소 8GB RAM, 권장 NVIDIA GPU (vLLM은 필수)

솔루션 한눈에 보기

아래 다이어그램은 5가지 주요 로컬 LLM 솔루션의 특성을 한눈에 비교합니다. 각 솔루션의 인터페이스 유형, 난이도, 성능 수준을 확인하세요.

5가지 로컬 LLM 솔루션 비교 솔루션 인터페이스 난이도 성능 Ollama 가장 인기 있는 도구 CLI REST 쉬움 LM Studio 초보자 친화적 GUI REST 매우 쉬움 LocalAI OpenAI 호환 API Docker API 보통 Text Gen WebUI 최대 커스터마이징 WebUI API 어려움 vLLM 프로덕션 최적화 Python API 고급 난이도 바: 길수록 어려움 | 성능 바: 길수록 높은 성능

그림 8: 5가지 로컬 LLM 솔루션 비교 - 인터페이스, 난이도, 성능 수준을 한눈에 파악

로컬 LLM의 장점과 단점

VS 로컬 LLM 🔒 데이터 프라이버시 민감 데이터가 외부로 전송되지 않음 💰 비용 절감 초기 투자 후 무제한 사용 📡 오프라인 작업 인터넷 연결 없이 완전한 기능 🔧 커스터마이징 모델 파인튜닝 및 완전 제어 자율성 + 프라이버시 클라우드 API 🏆 최고 품질 최신 대형 모델 (GPT-4, Claude) 쉬운 설정 API 키 하나로 바로 시작 🔄 자동 업데이트 항상 최신 모델 자동 반영 🖼️ 멀티모달 이미지, 음성, 비디오 지원 편의성 + 최신 기술

그림 7: 로컬 LLM vs 클라우드 API 비교 - 각각의 장점을 이해하고 상황에 맞게 선택

장점

장점
// 1. 데이터 프라이버시
• 민감한 데이터가 외부로 전송되지 않음
• 의료, 금융, 법률 분야에서 필수
• GDPR, HIPAA 등 규제 준수 용이

// 2. 비용 절감
• 초기 하드웨어 투자 후 무제한 사용
• API 종량제 비용 없음
• 대량 처리 시 특히 경제적

// 3. 오프라인 작업
• 인터넷 연결 불필요
• 네트워크 지연 없음
• 항공, 군사, 원격지 환경에서 유용

// 4. 커스터마이징
• 모델 파인튜닝 가능
• 프롬프트 템플릿 완전 제어
• 특정 도메인에 최적화

// 5. 제한 없는 실험
• Rate Limiting 없음
• 토큰 제한 없음 (하드웨어 한도 내)
• 개발 및 테스트 자유로움

단점

단점
// 1. 하드웨어 요구사항
┌──────────────┬────────────┬──────────────┬──────────────┐
│ 모델 크기    │ 최소 RAM   │ 권장 VRAM    │ 성능         │
├──────────────┼────────────┼──────────────┼──────────────┤
│ 3B (소형)    │ 8GB        │ 4GB          │ 빠름         │
│ 7B (중형)    │ 16GB       │ 8GB          │ 중간         │
│ 13B (대형)   │ 32GB       │ 16GB         │ 느림         │
│ 30B+ (초대형)│ 64GB+      │ 24GB+        │ 매우 느림    │
└──────────────┴────────────┴──────────────┴──────────────┘

// 2. 성능 제한
• 상용 API 대비 응답 품질 낮음
• 추론 속도 느림 (특히 CPU 사용 시)
• 멀티태스킹 시 리소스 경쟁

// 3. 유지보수 부담
• 모델 업데이트 수동 관리
• 서버 관리, 모니터링 필요
• 트러블슈팅 직접 해결

// 4. 초기 학습 곡선
• 모델 형식, 양자화 이해 필요
• CLI 도구 사용법 습득
• 성능 튜닝 복잡
권장 사용 사례
  • 로컬 LLM 적합: 민감 데이터 처리, 대량 배치 작업, 오프라인 환경, 실험/개발
  • 클라우드 API 적합: 최고 품질 요구, 소량 요청, 인프라 관리 회피, 멀티모달 기능

Ollama

Ollama는 로컬 LLM 실행을 위한 가장 인기 있는 도구로, Docker와 유사한 CLI 기반 워크플로우를 제공합니다.

Ollama 내부 아키텍처 CLI (ollama run/pull/list) 사용자 인터페이스 계층 서버 계층 REST API :11434 포트 모델 매니저 다운로드 / 캐시 / 버전 프롬프트 엔진 템플릿 / 컨텍스트 관리 추론 엔진 (llama.cpp) GGUF 모델 로딩 / 토큰 생성 / KV 캐시 CPU (AVX2/ARM NEON) 모든 플랫폼 / 기본 실행 GPU (CUDA/Metal/ROCm) 레이어 오프로딩 / 고속 추론 또는 요청 흐름

그림 9: Ollama 내부 아키텍처 - CLI에서 하드웨어까지 4계층 구조

설치

bash
# Linux/macOS
curl -fsSL https://ollama.com/install.sh | sh

# macOS (Homebrew)
brew install ollama

# Windows
# https://ollama.com/download 에서 설치 프로그램 다운로드

# 설치 확인
ollama --version
# ollama version 0.5.7

# 서버 시작 (백그라운드)
ollama serve &

# 모델 다운로드 (예: Llama 3.1)
ollama pull llama3.1:8b

# 모델 목록 확인
ollama list

# 대화형 테스트
ollama run llama3.1:8b

주요 모델

모델
인기 모델 (2026년 1월 기준):

// 범용 모델
llama3.1:8b          # Meta Llama 3.1 (8B 파라미터, 4.7GB)
llama3.1:70b         # Llama 3.1 (70B 파라미터, 40GB)
mistral:7b           # Mistral 7B (4.1GB)
mixtral:8x7b         # Mixtral MoE (26GB)
gemma2:9b            # Google Gemma 2 (5.4GB)

// 코딩 특화
codellama:7b         # Meta Code Llama (3.8GB)
deepseek-coder:6.7b  # DeepSeek Coder (3.8GB)
starcoder2:15b       # StarCoder 2 (9GB)

// 한국어 지원
solar:10.7b          # Upstage Solar (6.1GB)
eeve:10.8b           # yanolja EEVE (6.2GB)

// 경량 모델
phi3:3.8b            # Microsoft Phi-3 Mini (2.3GB)
qwen2:1.5b           # Alibaba Qwen 2 (934MB)

모델 이름 형식: "모델명:크기-양자화"
예시:
  llama3.1:8b        # 기본 양자화 (Q4_0)
  llama3.1:8b-q8_0   # Q8 양자화 (더 큼, 더 정확)
  llama3.1:8b-q4_K_M # Q4 K-Quant Medium
모델 양자화 파이프라인 높은 품질 / 큰 용량 낮은 품질 / 작은 용량 FP16 16비트 부동소수 ~16GB (8B) Q8_0 8비트 양자화 ~8.5GB (8B) Q4_K_M 4비트 K-Quant ~4.9GB (8B) 권장 Q4_0 4비트 기본 ~4.3GB (8B) Q2_K 2비트 ~2.8GB (8B) 용량 비교 (Llama 3.1 8B 기준) FP16 16GB Q8_0 8.5GB Q4_K_M 4.9GB Q4_0 4.3GB Q2_K 2.8GB

그림 11: 모델 양자화 파이프라인 - FP16에서 Q2_K까지 품질과 용량의 트레이드오프. Q4_K_M이 성능/용량 균형에서 권장

Ollama API 사용

python
# pip install ollama

import ollama

# 1. 기본 완성
response = ollama.chat(
    model='llama3.1:8b',
    messages=[
        {'role': 'user', 'content': 'Python으로 퀵소트를 구현해줘'}
    ]
)
print(response['message']['content'])

# 2. 스트리밍
for chunk in ollama.chat(
    model='llama3.1:8b',
    messages=[{'role': 'user', 'content': '긴 이야기 들려줘'}],
    stream=True
):
    print(chunk['message']['content'], end='', flush=True)

# 3. 다중 턴 대화
messages = [
    {'role': 'system', 'content': '너는 Python 전문가야.'},
    {'role': 'user', 'content': 'async/await란?'}
]
response = ollama.chat(model='llama3.1:8b', messages=messages)
messages.append(response['message'])
messages.append({'role': 'user', 'content': '예제 코드 보여줘'})
response = ollama.chat(model='llama3.1:8b', messages=messages)

# 4. 임베딩 생성
embedding = ollama.embeddings(
    model='nomic-embed-text',
    prompt='LLM은 대규모 언어 모델이다.'
)
print(len(embedding['embedding']))  # 768차원 벡터

# 5. 모델 정보
info = ollama.show('llama3.1:8b')
print(info['parameters'])
print(info['template'])

REST API (HTTP)

bash
# 기본 요청
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.1:8b",
  "messages": [
    {"role": "user", "content": "Hello, Ollama!"}
  ]
}'

# 스트리밍 응답
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.1:8b",
  "messages": [{"role": "user", "content": "Count to 10"}],
  "stream": true
}'

# 생성 파라미터 조정
curl http://localhost:11434/api/chat -d '{
  "model": "llama3.1:8b",
  "messages": [{"role": "user", "content": "Write a poem"}],
  "options": {
    "temperature": 0.8,
    "top_p": 0.9,
    "max_tokens": 500
  }
}'

커스텀 모델 (Modelfile)

modelfile
# Modelfile: 커스텀 프롬프트, 파라미터 설정
FROM llama3.1:8b

# 시스템 프롬프트
SYSTEM """
당신은 한국어 Python 코딩 어시스턴트입니다.
- 항상 한국어로 답변하세요.
- 코드에는 상세한 주석을 포함하세요.
- PEP 8 스타일을 준수하세요.
"""

# 생성 파라미터
PARAMETER temperature 0.7
PARAMETER top_p 0.9
PARAMETER top_k 40
PARAMETER repeat_penalty 1.1

# 컨텍스트 길이
PARAMETER num_ctx 4096

# 예시 대화
MESSAGE user 피보나치 함수 작성해줘
MESSAGE assistant 재귀와 반복문 두 가지 방식으로 구현하겠습니다...
bash
# Modelfile로 커스텀 모델 생성
ollama create my-korean-coder -f Modelfile

# 커스텀 모델 사용
ollama run my-korean-coder

# 공유 (Ollama Hub)
ollama push myusername/my-korean-coder

LM Studio

LM Studio는 GUI 기반의 사용자 친화적인 로컬 LLM 플랫폼입니다. 코드 없이 모델을 다운로드하고 테스트할 수 있습니다.

주요 특징

특징
✓ 직관적인 GUI 인터페이스
✓ HuggingFace 모델 브라우징 및 원클릭 다운로드
✓ 내장 채팅 UI (ChatGPT 스타일)
✓ OpenAI 호환 로컬 서버
✓ GPU 가속 자동 감지
✓ 모델 비교 및 벤치마크
✓ 프롬프트 템플릿 관리
✓ Windows, macOS, Linux 지원

사용 사례:
• 비개발자가 로컬 LLM 체험
• 다양한 모델 빠른 프로토타이핑
• 개발 전 모델 품질 평가
• ChatGPT 대체 (프라이버시 중시)

설치 및 사용

설치
1. https://lmstudio.ai/ 방문
2. OS에 맞는 설치 프로그램 다운로드
3. 설치 및 실행

// 모델 다운로드
1. 좌측 "Search" 탭 클릭
2. 모델 검색 (예: "llama 3.1 8b")
3. 원하는 양자화 선택 (Q4_K_M 권장)
4. "Download" 클릭

// 채팅 테스트
1. "Chat" 탭 클릭
2. 상단에서 모델 선택
3. 우측 설정에서 파라미터 조정
4. 메시지 입력 및 전송

// 로컬 서버 시작
1. "Local Server" 탭 클릭
2. 모델 선택 및 로드
3. "Start Server" 클릭
4. 기본 URL: http://localhost:1234/v1

API 사용 (OpenAI 호환)

python
# pip install openai

from openai import OpenAI

# LM Studio 로컬 서버에 연결
client = OpenAI(
    base_url="http://localhost:1234/v1",
    api_key="lm-studio"  # 임의 값 (필수지만 검증 안함)
)

# OpenAI API와 동일한 방식으로 사용
response = client.chat.completions.create(
    model="local-model",  # LM Studio에서 로드한 모델
    messages=[
        {"role": "system", "content": "너는 도움이 되는 어시스턴트야."},
        {"role": "user", "content": "LM Studio의 장점은?"}
    ],
    temperature=0.7,
    max_tokens=500
)

print(response.choices[0].message.content)

# 스트리밍
stream = client.chat.completions.create(
    model="local-model",
    messages=[{"role": "user", "content": "1부터 20까지 세어줘"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

LM Studio 팁

// 1. 모델 선택"Q4_K_M" 양자화: 균형잡힌 성능/메모리 (권장)
• "Q8_0": 더 높은 품질, 2배 메모리
• "Q2_K": 최소 메모리, 품질 저하

// 2. GPU 설정
• Settings → Hardware → GPU Offload
• 레이어 수 조정 (더 많이 = 더 빠르지만 VRAM 많이 사용)
• VRAM 부족 시 일부 레이어만 GPU에 로드

// 3. 컨텍스트 길이
• 기본 2048토큰 → 필요시 4096, 8192로 증가
• 길수록 메모리 사용량 증가
• 모델의 학습 컨텍스트 초과 시 품질 저하

// 4. 프롬프트 포맷
• 모델마다 다른 프롬프트 템플릿 사용
• LM Studio가 자동 감지하지만 수동 설정 가능
• Settings → Prompt Format 확인

// 5. 성능 모니터링
• 하단 상태바에서 토큰/초 확인
• CPU 사용 시: 2-5 tok/s
• GPU 사용 시: 20-50 tok/s (모델/하드웨어 따라 다름)

OpenAI 호환 API 게이트웨이

로컬 LLM 솔루션들은 대부분 OpenAI 호환 API를 제공합니다. 이를 통해 기존 OpenAI API 기반 코드를 수정 없이 로컬 모델로 전환할 수 있습니다.

OpenAI 호환 API 게이트웨이 기존 코드 openai.ChatCompletion .create( model="llama3.1" messages=[...] ) base_url 변경만! 코드 변경 최소화 Ollama localhost:11434/v1 LM Studio localhost:1234/v1 LocalAI localhost:8080/v1 vLLM localhost:8000/v1 동일한 API 형식 /v1/chat/completions /v1/completions

그림 10: OpenAI 호환 API 게이트웨이 - base_url만 변경하면 동일한 코드로 다양한 로컬 LLM 백엔드 사용 가능

python
# OpenAI 호환 API로 로컬 LLM 사용하기
from openai import OpenAI

# Ollama 사용
client_ollama = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"  # 아무 값이나 가능
)

# LM Studio 사용
client_lm = OpenAI(
    base_url="http://localhost:1234/v1",
    api_key="lm-studio"
)

# LocalAI 사용
client_local = OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="localai"
)

# vLLM 사용
client_vllm = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="vllm"
)

# 동일한 API 호출 코드
def chat(client, model, message):
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": message}]
    )
    return response.choices[0].message.content

Claude Code CLI용 LiteLLM 프록시

Claude Code CLI는 OpenAI 호환 API(/v1/chat/completions)가 아닌 Anthropic Messages API(/v1/messages) 포맷을 사용합니다. 따라서 Ollama, LM Studio 등에 직접 연결할 수 없고, LiteLLM 프록시를 통한 API 포맷 변환이 필요합니다.

LiteLLM은 현재 Anthropic Messages API 포맷 변환을 지원하는 유일한 오픈소스 게이트웨이입니다. 입력으로 Anthropic 포맷을 받아 백엔드별 API로 변환해줍니다.

백엔드별 litellm_config.yaml 설정

Ollama 백엔드:

yaml — litellm_config.yaml (Ollama)
model_list:
  - model_name: claude-sonnet-4-20250514
    litellm_params:
      model: ollama/qwen2.5-coder:14b
      api_base: http://localhost:11434

  - model_name: claude-haiku-4-20250414
    litellm_params:
      model: ollama/qwen2.5-coder:7b
      api_base: http://localhost:11434

litellm_settings:
  drop_params: true

LM Studio 백엔드:

yaml — litellm_config.yaml (LM Studio)
model_list:
  - model_name: claude-sonnet-4-20250514
    litellm_params:
      model: openai/qwen2.5-coder-14b-instruct
      api_base: http://localhost:1234/v1
      api_key: lm-studio

litellm_settings:
  drop_params: true

vLLM 백엔드:

yaml — litellm_config.yaml (vLLM)
model_list:
  - model_name: claude-sonnet-4-20250514
    litellm_params:
      model: openai/Qwen/Qwen2.5-Coder-14B-Instruct
      api_base: http://localhost:8000/v1
      api_key: vllm

litellm_settings:
  drop_params: true

Docker Compose 원커맨드 구성

Ollama + LiteLLM을 Docker Compose로 한번에 구성할 수 있습니다.

yaml — docker-compose.yml
version: '3.8'
services:
  ollama:
    image: ollama/ollama:latest
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - capabilities: [gpu]

  litellm:
    image: ghcr.io/berriai/litellm:main-latest
    ports:
      - "4000:4000"
    volumes:
      - ./litellm_config.yaml:/app/config.yaml
    command: ["--config", "/app/config.yaml", "--port", "4000"]
    depends_on:
      - ollama

volumes:
  ollama_data:
bash
# 서비스 시작
docker compose up -d

# 모델 다운로드 (최초 1회)
docker exec -it ollama ollama pull qwen2.5-coder:14b

# Claude Code CLI 연결
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="sk-any-string"
claude
관련 문서: Claude CLI 가이드 — Local LLM 게이트웨이 연동에서 환경 변수 설정, 아키텍처 다이어그램, 제약 사항 등을 상세히 다룹니다.

LocalAI

LocalAI는 OpenAI API와 완벽히 호환되는 오픈소스 프로젝트로, 다양한 모델 형식(GGUF, GGML, PyTorch)을 지원합니다.

Docker로 설치

bash
# Docker Compose 파일 생성
cat <<EOF > docker-compose.yml
version: '3.8'
services:
  localai:
    image: quay.io/go-skynet/local-ai:latest
    ports:
      - "8080:8080"
    volumes:
      - ./models:/models
      - ./images:/tmp/generated/images
    environment:
      - THREADS=4
      - CONTEXT_SIZE=4096
      - DEBUG=true
    restart: unless-stopped
EOF

# 컨테이너 시작
docker-compose up -d

# 로그 확인
docker-compose logs -f

# 모델 다운로드 (예: Llama 3.1)
mkdir -p models
cd models
wget https://huggingface.co/TheBloke/Llama-3.1-8B-Instruct-GGUF/resolve/main/llama-3.1-8b-instruct.Q4_K_M.gguf

모델 설정 (YAML)

yaml
# models/llama3.yaml
name: llama3-8b
backend: llama
parameters:
  model: llama-3.1-8b-instruct.Q4_K_M.gguf
  temperature: 0.7
  top_k: 40
  top_p: 0.9
  max_tokens: 2048
  context_size: 4096

# 프롬프트 템플릿 (Llama 3 형식)
template:
  chat: |
    <|begin_of_text|>
    {{.Input}}
    <|start_header_id|>assistant<|end_header_id|>
  completion: |
    {{.Input}}

# GPU 설정
f16: true
gpu_layers: 35  # GPU에 오프로드할 레이어 수

# 임베딩 지원
embeddings: true

LocalAI API 사용

python
from openai import OpenAI

# LocalAI 서버에 연결
client = OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="not-needed"
)

# 1. 채팅 완성
response = client.chat.completions.create(
    model="llama3-8b",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain quantum computing in simple terms."}
    ]
)

# 2. 텍스트 완성 (레거시)
response = client.completions.create(
    model="llama3-8b",
    prompt="Once upon a time",
    max_tokens=100
)

# 3. 임베딩
response = client.embeddings.create(
    model="llama3-8b",
    input="LocalAI is an OpenAI alternative."
)
embedding = response.data[0].embedding

# 4. 이미지 생성 (Stable Diffusion 백엔드 필요)
response = client.images.generate(
    model="stable-diffusion",
    prompt="A cat wearing sunglasses",
    size="512x512"
)

고급 기능

features
// 1. 다중 모델 동시 실행
• 모델별 YAML 파일 작성
• 동일 LocalAI 인스턴스에서 여러 모델 제공
• 요청 시 model 파라미터로 선택

// 2. Function Calling
• OpenAI 스타일 도구 사용 지원
• JSON 스키마 기반 함수 정의
• 호환 모델: Llama 3.1, Mistral

// 3. 오디오 처리
• Whisper 백엔드: 음성 → 텍스트
• TTS 백엔드: 텍스트 → 음성

// 4. 이미지 생성
• Stable Diffusion 통합
• text-to-image, image-to-image

// 5. 프롬프트 템플릿
• 모델별 커스텀 템플릿
• ChatML, Alpaca, Vicuna 등 지원
• Jinja2 스타일 변수 치환

Text Generation WebUI (oobabooga)

Text Generation WebUI는 가장 많은 기능과 커스터마이징 옵션을 제공하는 고급 로컬 LLM 플랫폼입니다.

설치

bash
# 1. 저장소 클론
git clone https://github.com/oobabooga/text-generation-webui
cd text-generation-webui

# 2. 원클릭 설치 스크립트 실행
# Linux/macOS
./start_linux.sh
# Windows
start_windows.bat

# 3. 브라우저에서 접속
# http://localhost:7860

# 수동 설치 (고급 사용자)
conda create -n textgen python=3.11
conda activate textgen
pip install -r requirements.txt

# GPU 지원 (NVIDIA)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# 실행
python server.py --listen --api

주요 기능

특징
✓ 다양한 모델 로더:
  • Transformers (HuggingFace)
  • llama.cpp (GGUF)
  • GPTQ, AWQ, ExLlama (양자화)
  • AutoGPTQ, bitsandbytes

✓ 여러 인터페이스:
  • Chat: ChatGPT 스타일 대화
  • Default: 단순 텍스트 완성
  • Notebook: Jupyter 스타일
  • API: OpenAI 호환 엔드포인트

✓ 확장 시스템:
  • 커뮤니티 플러그인
  • RAG (Retrieval Augmented Generation)
  • TTS, STT 통합
  • Stable Diffusion 연동

✓ 캐릭터/페르소나:
  • 사전 정의된 대화 스타일
  • 커스텀 시스템 프롬프트
  • 예시 대화 주입

✓ 고급 샘플링:
  • Temperature, Top-P, Top-K
  • Mirostat, DRY, Contrastive Search
  • Repetition Penalty 세밀 조정

API 사용

bash
# API 서버 모드로 실행
python server.py --api --listen

# OpenAI 호환 API
curl http://localhost:5000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ]
  }'

# 전용 API (더 많은 파라미터)
curl http://localhost:5000/api/v1/generate \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Once upon a time",
    "max_new_tokens": 200,
    "temperature": 0.7,
    "top_p": 0.9,
    "top_k": 40,
    "repetition_penalty": 1.1,
    "do_sample": true
  }'
python
import requests

# 1. OpenAI 호환 방식
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:5000/v1",
    api_key="not-needed"
)

response = client.chat.completions.create(
    model="gpt-3.5-turbo",  # 임의 이름 (무시됨)
    messages=[{"role": "user", "content": "Hi!"}]
)

# 2. 전용 API (더 많은 제어)
url = "http://localhost:5000/api/v1/generate"
payload = {
    "prompt": "Explain neural networks",
    "max_new_tokens": 300,
    "temperature": 0.7,
    "top_p": 0.9,
    "repetition_penalty": 1.15,
    "do_sample": True,
    "seed": 42  # 재현 가능한 출력
}

response = requests.post(url, json=payload)
result = response.json()
print(result['results'][0]['text'])

유용한 확장

확장
// 설치: Session 탭 → Extensions → 확장 이름 입력 → Install

1. superbooga - RAG (문서 기반 답변)
   • PDF, TXT, DOCX 임베딩
   • ChromaDB 벡터 저장소
   • 컨텍스트 자동 주입

2. openai - OpenAI 호환 API 서버
   • /v1/chat/completions 엔드포인트
   • Function Calling 지원

3. silero_tts - 음성 합성
   • 다국어 TTS
   • 캐릭터별 음성 설정

4. whisper_stt - 음성 인식
   • 음성 입력
   • 실시간 전사

5. sd_api_pictures - 이미지 생성
   • Stable Diffusion WebUI 연동
   • 대화 중 이미지 생성 명령

6. long_term_memory - 장기 기억
   • 대화 히스토리 벡터화
   • 과거 대화 검색 및 참조

vLLM (프로덕션 추론 서버)

vLLM은 UC Berkeley LMSYS에서 개발한 고성능 LLM 추론 엔진으로, 프로덕션 환경에서 최고의 처리량과 효율성을 제공합니다.

vLLM이란?

개요
// vLLM의 핵심 강점

1. PagedAttention - 메모리 효율성
• KV 캐시를 페이지 단위로 관리 (OS의 가상 메모리 기법 응용)
• 기존 대비 24배 높은 처리량
• 메모리 단편화 최소화

2. Continuous Batching - 동적 배칭
• 요청별 독립적 처리 (서로 다른 완성 길이)
• 새 요청 즉시 배치에 추가 (대기 시간 감소)
• GPU 유휴 시간 최소화

3. 빠른 모델 실행
• CUDA 커널 최적화
• Tensor Parallelism (다중 GPU)
• FP16, BF16, INT8 양자화 지원

4. OpenAI 호환 API
• 기존 OpenAI 클라이언트 코드 그대로 사용
• /v1/completions, /v1/chat/completions 엔드포인트
• 스트리밍 지원

// 사용 사례
✓ 대규모 서비스 (높은 QPS 요구)
✓ API 서비스 제공 (OpenAI 대체)
✓ 실시간 추론 (낮은 지연 시간)
✓ 비용 최적화 (GPU 활용률 극대화)

// 제한사항
✗ GGUF 형식 미지원 (PyTorch/Safetensors만)
✗ CPU 전용 실행 불가 (GPU 필수)
✗ 설치 및 설정 복잡 (초보자에게 어려움)

설치

bash
# 필수 요구사항
# - Linux (Ubuntu 20.04+)
# - Python 3.8-3.11
# - CUDA 11.8+ (NVIDIA GPU)
# - 최소 16GB GPU VRAM 권장

# 1. pip 설치 (가장 간단)
pip install vllm

# 2. CUDA 버전 지정 설치
pip install vllm --extra-index-url https://download.pytorch.org/whl/cu121

# 3. Docker 사용 (권장 - 환경 격리)
docker pull vllm/vllm-openai:latest

# 4. 소스에서 빌드 (최신 기능)
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .

# 설치 확인
python -c "import vllm; print(vllm.__version__)"
# 0.6.3 (2026년 1월 기준)

# GPU 확인
nvidia-smi
# CUDA Version: 12.1 이상 권장

기본 사용법

python
from vllm import LLM, SamplingParams

# 1. 모델 로드
llm = LLM(
    model="meta-llama/Llama-3.1-8B-Instruct",  # HuggingFace 모델 ID
    tensor_parallel_size=1,  # GPU 개수
    gpu_memory_utilization=0.9,  # GPU 메모리 사용률 (0.0-1.0)
    max_model_len=4096  # 최대 컨텍스트 길이
)

# 2. 샘플링 파라미터 설정
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=256,
    stop=["", "\n\n"]  # 종료 토큰
)

# 3. 단일 프롬프트 생성
prompts = ["Explain quantum computing in simple terms."]
outputs = llm.generate(prompts, sampling_params)

for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt}")
    print(f"Generated: {generated_text}")

# 4. 배치 추론 (여러 프롬프트 동시 처리)
prompts = [
    "What is machine learning?",
    "Explain neural networks.",
    "What is deep learning?"
]
outputs = llm.generate(prompts, sampling_params)

# 5. 대화형 프롬프트 (ChatML 형식)
from vllm import ChatCompletionMessage

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Write a Python function to calculate factorial."}
]

# 모델별 채팅 템플릿 적용
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

outputs = llm.generate([prompt], sampling_params)
print(outputs[0].outputs[0].text)

OpenAI 호환 API 서버

bash
# 1. 기본 서버 시작
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --port 8000

# 2. 고급 설정
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --port 8000 \
    --host 0.0.0.0 \
    --tensor-parallel-size 2 \
    --gpu-memory-utilization 0.95 \
    --max-model-len 8192 \
    --dtype bfloat16 \
    --disable-log-requests

# 3. Docker로 서버 실행
docker run --runtime nvidia --gpus all \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    -p 8000:8000 \
    --ipc=host \
    vllm/vllm-openai:latest \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --port 8000

# 4. 환경 변수 설정
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export CUDA_VISIBLE_DEVICES=0,1

# 5. 서버 헬스체크
curl http://localhost:8000/health
# {"status": "ok"}

# 6. 모델 목록 조회
curl http://localhost:8000/v1/models

클라이언트 사용

python
from openai import OpenAI

# vLLM 서버에 연결 (OpenAI SDK 사용)
client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="EMPTY"  # vLLM은 API 키 검증 안함
)

# 1. 채팅 완성
response = client.chat.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    messages=[
        {"role": "system", "content": "You are a Python expert."},
        {"role": "user", "content": "Write a binary search function."}
    ],
    temperature=0.7,
    max_tokens=512
)

print(response.choices[0].message.content)

# 2. 스트리밍
stream = client.chat.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    messages=[{"role": "user", "content": "Count to 20"}],
    stream=True,
    max_tokens=100
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

# 3. 텍스트 완성 (레거시)
response = client.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    prompt="Once upon a time",
    max_tokens=50,
    temperature=0.8
)

print(response.choices[0].text)

# 4. 다중 완성 (n > 1)
response = client.chat.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    messages=[{"role": "user", "content": "창의적인 회사 이름 제안해줘"}],
    n=5,  # 5개의 다른 완성 생성
    temperature=1.0
)

for i, choice in enumerate(response.choices):
    print(f"{i+1}. {choice.message.content}")

고급 기능

python
# 1. Tensor Parallelism (다중 GPU)
# 큰 모델을 여러 GPU에 분산
llm = LLM(
    model="meta-llama/Llama-3.1-70B-Instruct",
    tensor_parallel_size=4,  # 4개 GPU 사용
    dtype="bfloat16"
)

# 2. 양자화 (메모리 절약)
llm = LLM(
    model="meta-llama/Llama-3.1-8B-Instruct",
    quantization="awq",  # awq, gptq, squeezellm
    dtype="half"
)

# 3. 프롬프트 어댑터 (LoRA)
llm = LLM(
    model="meta-llama/Llama-3.1-8B-Instruct",
    enable_lora=True
)

# LoRA 어댑터 로드 및 요청
outputs = llm.generate(
    prompts,
    sampling_params,
    lora_request=LoRARequest("adapter1", 1, "/path/to/lora")
)

# 4. Prefix Caching (공통 프리픽스 재사용)
# 시스템 프롬프트 등 반복되는 프리픽스 캐싱
llm = LLM(
    model="meta-llama/Llama-3.1-8B-Instruct",
    enable_prefix_caching=True
)

# 5. Guided Decoding (구조화된 출력)
from vllm import SamplingParams

# JSON 출력 강제
json_schema = """{
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
    }
}"""

sampling_params = SamplingParams(
    temperature=0.7,
    guided_json=json_schema
)

# 6. 멀티모달 (비전)
from vllm import LLM, SamplingParams

llm = LLM(model="llava-hf/llava-v1.6-mistral-7b-hf")

# 이미지 + 텍스트 입력
outputs = llm.generate({
    "prompt": "USER: <image>\nWhat's in this image?\nASSISTANT:",
    "multi_modal_data": {"image": "path/to/image.jpg"}
})

성능 최적화

최적화
// 1. GPU 메모리 활용 최대화
--gpu-memory-utilization 0.95
# 기본값 0.9, 최대 0.95 권장
# 1.0으로 설정 시 OOM 위험

// 2. 배치 크기 조정
--max-num-seqs 256
# 동시 처리 시퀀스 수
# 높을수록 처리량 증가, 메모리 사용 증가

// 3. Block Size 튜닝
--block-size 16
# PagedAttention 블록 크기
# 기본값 16, 메모리에 따라 조정

// 4. Speculative Decoding
--speculative-model "meta-llama/Llama-3.2-1B"
# 작은 모델로 예측 → 큰 모델로 검증
# 2-3배 속도 향상 (품질 동일)

// 5. Flash Attention
--use-flash-attn
# 메모리 효율적인 어텐션 (자동 활성화)

// 6. 컨텍스트 길이 제한
--max-model-len 4096
# 필요한 만큼만 설정
# 메모리 사용량 = O(sequence_length^2)

// 7. KV Cache 데이터 타입
--kv-cache-dtype fp8
# auto, fp8, fp16 (기본값)
# fp8: 메모리 절약, 약간의 품질 저하

// 8. 토큰 처리량 모니터링
# 로그에서 확인:
# "Avg prompt throughput: 1234 tokens/s"
# "Avg generation throughput: 567 tokens/s"

프로덕션 배포

yaml
# docker-compose.yml
version: '3.8'

services:
  vllm:
    image: vllm/vllm-openai:latest
    runtime: nvidia
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    ports:
      - "8000:8000"
    volumes:
      - ~/.cache/huggingface:/root/.cache/huggingface
    environment:
      - HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
    command:
      - "--model"
      - "meta-llama/Llama-3.1-8B-Instruct"
      - "--port"
      - "8000"
      - "--host"
      - "0.0.0.0"
      - "--gpu-memory-utilization"
      - "0.95"
      - "--max-model-len"
      - "8192"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
python
# 프로덕션 클라이언트 (에러 처리, 재시도)
from openai import OpenAI
from tenacity import retry, stop_after_attempt, wait_exponential

client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=10)
)
def generate_with_retry(messages, **kwargs):
    try:
        response = client.chat.completions.create(
            model="meta-llama/Llama-3.1-8B-Instruct",
            messages=messages,
            **kwargs
        )
        return response.choices[0].message.content
    except Exception as e:
        print(f"Error: {e}")
        raise

# 사용
result = generate_with_retry(
    messages=[{"role": "user", "content": "Hello"}],
    temperature=0.7,
    max_tokens=100
)

벤치마크

벤치마크
처리량 비교 (Llama 3.1 8B, A100 80GB, 2026년 1월):

┌─────────────────┬─────────────┬─────────────┬─────────────┐
│ 플랫폼          │ Throughput  │ Latency     │ GPU 사용률  │
├─────────────────┼─────────────┼─────────────┼─────────────┤
│ vLLM            │ 2400 tok/s  │ 18ms        │ 95%         │
│ Text Gen WebUI  │ 850 tok/s   │ 45ms        │ 70%         │
│ Ollama          │ 720 tok/s   │ 52ms        │ 65%         │
│ HF Transformers │ 320 tok/s   │ 125ms       │ 50%         │
└─────────────────┴─────────────┴─────────────┴─────────────┘

동시 요청 처리 (100 concurrent requests):
┌─────────────────┬─────────────┬─────────────┬─────────────┐
│ 플랫폼          │ QPS         │ P50 Latency │ P99 Latency │
├─────────────────┼─────────────┼─────────────┼─────────────┤
│ vLLM            │ 45          │ 320ms       │ 850ms       │
│ Text Gen WebUI  │ 12          │ 1.2s        │ 3.5s        │
│ Ollama          │ 8           │ 1.8s        │ 5.2s        │
└─────────────────┴─────────────┴─────────────┴─────────────┘

메모리 효율성 (Llama 3.1 70B):
┌─────────────────┬─────────────┬─────────────┐
│ 플랫폼          │ VRAM 사용   │ 배치 크기   │
├─────────────────┼─────────────┼─────────────┤
│ vLLM            │ 78GB        │ 128         │
│ Transformers    │ 78GB        │ 32          │
└─────────────────┴─────────────┴─────────────┘

// 실제 측정 방법
# 벤치마크 스크립트
python benchmarks/benchmark_throughput.py \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --input-len 128 \
    --output-len 256 \
    --num-prompts 1000

트러블슈팅

문제
// 1. Out of Memory
증상: RuntimeError: CUDA out of memory
해결:
  • --gpu-memory-utilization 낮추기 (0.9 → 0.8)
  • --max-model-len 줄이기
  • --max-num-seqs 감소
  • 양자화 사용 (--quantization awq)

// 2. 느린 첫 요청
증상: 첫 요청만 매우 느림
해결:
  • 모델 로딩 시간 (정상)
  • --enforce-eager 옵션 (CUDA 그래프 비활성화)

// 3. Tensor Parallel 실패
증상: Multi-GPU 사용 시 오류
해결:
  • CUDA_VISIBLE_DEVICES 확인
  • NCCL 설치 확인: pip install nccl
  • --tensor-parallel-size를 GPU 개수와 일치

// 4. 모델 다운로드 실패
증상: OSError: Can't load model
해결:
  • HuggingFace 토큰 설정:
    export HUGGING_FACE_HUB_TOKEN=your_token
  • 모델 경로 확인 (로컬 경로 또는 HF ID)
  • 네트워크 연결 확인

// 5. 낮은 처리량
증상: 예상보다 낮은 tok/s
해결:
  • GPU 활용률 확인 (nvidia-smi)
  • --max-num-seqs 증가
  • 배치 요청 사용 (단일 요청 대신)
  • CPU 병목 확인 (프로파일링)

// 6. CUDA 버전 불일치
증상: CUDA driver version is insufficient
해결:
  • nvidia-smi로 CUDA 버전 확인
  • PyTorch CUDA 버전과 일치시키기
  • 드라이버 업데이트

추가 리소스

리소스
// 공식 자료
• 공식 문서: https://docs.vllm.ai/
• GitHub: https://github.com/vllm-project/vllm
• Paper: https://arxiv.org/abs/2309.06180
• 블로그: https://blog.vllm.ai/

// 커뮤니티
• Discord: https://discord.gg/vllm
• GitHub Discussions: vllm-project/vllm/discussions

// 벤치마크
• 공식 벤치마크: vllm-project/vllm/benchmarks
• LMSys Chatbot Arena: https://chat.lmsys.org/

// 관련 프로젝트
• Ray Serve + vLLM: 분산 배포
• BentoML + vLLM: MLOps 통합
• LiteLLM + vLLM: 멀티 프로바이더 라우팅

성능 비교 및 벤치마크

하드웨어 요구사항

요구사항
모델별 최소 사양 (Q4 양자화 기준):

┌────────────┬────────────┬──────────────┬──────────────┬──────────────┐
│ 모델 크기  │ 최소 RAM   │ 권장 RAM     │ VRAM (GPU)   │ 속도 (tok/s) │
├────────────┼────────────┼──────────────┼──────────────┼──────────────┤
│ 3B         │ 4GB        │ 8GB          │ 4GB          │ 30-50        │
│ 7B         │ 8GB        │ 16GB         │ 6GB          │ 20-40        │
│ 13B        │ 16GB       │ 32GB         │ 10GB         │ 10-25        │
│ 30B        │ 32GB       │ 64GB         │ 20GB         │ 5-15         │
│ 70B        │ 64GB       │ 128GB        │ 40GB         │ 2-8          │
└────────────┴────────────┴──────────────┴──────────────┴──────────────┘

CPU vs GPU 성능 차이:
• CPU (16코어): 2-5 tok/s (7B 모델)
• RTX 3060 (12GB): 20-30 tok/s
• RTX 4090 (24GB): 60-100 tok/s
• Apple M1 Max (64GB): 15-25 tok/s (Metal 가속)

양자화 수준별 트레이드오프:
┌──────────┬──────────────┬──────────────┬──────────────┐
│ 양자화   │ 크기 (7B)    │ 품질         │ 속도         │
├──────────┼──────────────┼──────────────┼──────────────┤
│ FP16     │ 14GB         │ 최고         │ 기준         │
│ Q8_0     │ 7.5GB        │ 매우 높음    │ 1.2x         │
│ Q6_K     │ 5.8GB        │ 높음         │ 1.4x         │
│ Q4_K_M   │ 4.1GB        │ 중간 (권장)  │ 1.8x         │
│ Q4_0     │ 3.8GB        │ 중하         │ 2.0x         │
│ Q2_K     │ 2.5GB        │ 낮음         │ 2.5x         │
└──────────┴──────────────┴──────────────┴──────────────┘

품질 벤치마크

벤치마크
일반 능력 (MMLU, HumanEval 기준, 2026년 1월):

// 범용 모델
┌──────────────────┬──────────┬────────────┬──────────────┐
│ 모델             │ MMLU     │ HumanEval  │ 한국어       │
├──────────────────┼──────────┼────────────┼──────────────┤
│ Llama 3.1 70B    │ 79.5%    │ 67.8%      │ 보통         │
│ Llama 3.1 8B     │ 68.4%    │ 58.2%      │ 보통         │
│ Mistral 7B       │ 62.5%    │ 40.2%      │ 낮음         │
│ Gemma 2 9B       │ 71.3%    │ 51.8%      │ 보통         │
│ Qwen 2.5 7B      │ 70.3%    │ 54.2%      │ 높음         │
│ Solar 10.7B      │ 66.2%    │ 45.3%      │ 매우 높음    │
└──────────────────┴──────────┴────────────┴──────────────┘

// 코딩 특화 모델
┌──────────────────┬────────────┬────────────┬──────────────┐
│ 모델             │ HumanEval  │ MBPP       │ 비고         │
├──────────────────┼────────────┼────────────┼──────────────┤
│ DeepSeek 33B     │ 79.3%      │ 70.2%      │ 최고 코딩    │
│ Code Llama 34B   │ 53.7%      │ 56.2%      │ 범용 코딩    │
│ StarCoder 2 15B  │ 46.2%      │ 54.5%      │ 다국어       │
│ Qwen 2.5 Coder   │ 65.9%      │ 61.8%      │ 균형잡힘     │
└──────────────────┴────────────┴────────────┴──────────────┘

실사용 평가 (주관적):
• 대화 자연스러움: Llama 3.1 > Gemma 2 > Mistral
• 긴 컨텍스트: Llama 3.1 > Qwen 2.5 > Mistral
• 코드 생성: DeepSeek > Code Llama > Llama 3.1
• 한국어: Solar > EEVE > Qwen 2.5 > Llama 3.1
• 추론 능력: Llama 3.1 70B > Qwen 2.5 > Gemma 2

플랫폼 비교

비교
┌─────────────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ 기능            │ Ollama  │ LM Stud │ LocalAI │ WebUI   │ vLLM    │
├─────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ 설치 난이도     │ ★☆☆☆☆  │ ★☆☆☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★☆  │
│ GUI             │ ✗       │ ✓       │ ✗       │ ✓       │ ✗       │
│ CLI             │ ✓       │ ✗       │ ✗       │ ✗       │ ✓       │
│ Python API      │ ✓       │ ✗       │ ✗       │ ✓       │ ✓       │
│ OpenAI 호환     │ ✗       │ ✓       │ ✓       │ ✓       │ ✓       │
│ 모델 형식       │ GGUF    │ GGUF    │ ALL     │ ALL     │ PyTorch │
│ GPU 최적화      │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★☆  │ ★★★★★  │
│ CPU 지원        │ ✓       │ ✓       │ ✓       │ ✓       │ ✗       │
│ 다중 GPU        │ ✗       │ ✗       │ ✗       │ ✓       │ ✓       │
│ 배치 처리       │ 기본    │ 기본    │ 기본    │ 고급    │ 최적화  │
│ 처리량          │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★★  │
│ 지연 시간       │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★★  │
│ 메모리 효율성   │ ★★★☆☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★☆  │ ★★★★★  │
│ 확장성          │ ★★☆☆☆  │ ★☆☆☆☆  │ ★★★★☆  │ ★★★★★  │ ★★★★★  │
│ 양자화 지원     │ 기본    │ 기본    │ 제한적  │ 전체    │ 고급    │
│ LoRA 지원       │ ✗       │ ✗       │ ✗       │ ✓       │ ✓       │
│ 스트리밍        │ ✓       │ ✓       │ ✓       │ ✓       │ ✓       │
│ 커뮤니티        │ ★★★★★  │ ★★★★☆  │ ★★★☆☆  │ ★★★★★  │ ★★★★☆  │
│ 문서 품질       │ ★★★★☆  │ ★★★★☆  │ ★★★☆☆  │ ★★★☆☆  │ ★★★★☆  │
│ 프로덕션 사용   │ ★★★☆☆  │ ★☆☆☆☆  │ ★★★★☆  │ ★★☆☆☆  │ ★★★★★  │
│ 학습 곡선       │ 낮음    │ 매우낮음│ 중간    │ 높음    │ 중상    │
└─────────────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

// 권장 사용 사례

Ollama
✓ 개발자 로컬 테스트
✓ CLI 선호
✓ 빠른 모델 전환
✓ GGUF 모델 사용
✗ 프로덕션 배포
✗ 고성능 요구

LM Studio
✓ 비개발자
✓ GUI 필수
✓ 모델 비교 테스트
✓ 간단한 채팅
✗ 자동화/스크립팅
✗ 서버 배포

LocalAI
✓ OpenAI 완전 대체
✓ 다양한 모델 형식
✓ 멀티모달 (TTS, STT, Image)
✓ Docker 배포
✗ 최고 성능 필요
✗ 단순함 우선

Text Generation WebUI
✓ 고급 사용자
✓ 최대 커스터마이징
✓ 실험 및 연구
✓ 확장 플러그인
✗ 프로덕션 안정성
✗ 간단한 API 서버

vLLM
✓ 프로덕션 서비스
✓ 대규모 트래픽 (높은 QPS)
✓ 최고 성능 필요
✓ 다중 GPU 활용
✓ 비용 최적화 (GPU 효율)
✗ CPU만 사용
✗ GGUF 모델
✗ 초보자

// 성능 순위 (동일 모델, 동일 하드웨어 기준)

처리량 (Throughput):
  1. vLLM (2400 tok/s)
  2. Text Gen WebUI (850 tok/s)
  3. Ollama (720 tok/s)
  4. LocalAI (680 tok/s)
  5. LM Studio (650 tok/s)

지연 시간 (Latency):
  1. vLLM (18ms)
  2. Text Gen WebUI (45ms)
  3. Ollama (52ms)
  4. LocalAI (58ms)
  5. LM Studio (62ms)

메모리 효율성:
  1. vLLM (PagedAttention)
  2. Text Gen WebUI
  3. Ollama
  4. LocalAI
  5. LM Studio

사용 편의성:
  1. LM Studio
  2. Ollama
  3. LocalAI
  4. Text Gen WebUI
  5. vLLM

성능 최적화

GPU 최적화

최적화
// 1. 레이어 오프로드
# Ollama
OLLAMA_NUM_GPU_LAYERS=35 ollama run llama3.1:8b

# llama.cpp 직접 사용
./main -m model.gguf -ngl 35  # --n-gpu-layers

// 2. 배치 크기 조정
# 더 큰 배치 = 높은 처리량, 더 많은 VRAM
# Text Generation WebUI
python server.py --auto-devices --gpu-memory 10 --batch-size 512

// 3. Flash Attention
# 메모리 효율적인 어텐션 (CUDA 지원 GPU)
pip install flash-attn
python server.py --flash-attn

// 4. 양자화 선택
# VRAM 부족 시: Q4_K_M 또는 Q4_0
# 품질 우선: Q6_K 또는 Q8_0
ollama pull llama3.1:8b-q4_K_M
ollama pull llama3.1:8b-q8_0

// 5. 컨텍스트 길이 제한
# 긴 컨텍스트 = 메모리 사용량 증가
# 필요한 만큼만 설정
OLLAMA_CTX_SIZE=2048 ollama run llama3.1:8b

GPU 레이어 오프로딩 상세 설정

Ollama는 여러 환경 변수를 통해 GPU 활용을 세밀하게 제어할 수 있습니다. 특히 VRAM이 제한된 환경에서는 이 설정들이 핵심적인 역할을 합니다.

bash
# OLLAMA_NUM_GPU: GPU에 오프로드할 레이어 수
# 0 = CPU만 사용, -1 = 모든 레이어를 GPU에 (기본값: 자동 감지)
OLLAMA_NUM_GPU=0 ollama run llama3.1:8b   # CPU 전용
OLLAMA_NUM_GPU=-1 ollama run llama3.1:8b  # 전체 GPU
OLLAMA_NUM_GPU=20 ollama run llama3.1:8b  # 20개 레이어만 GPU

# OLLAMA_MAX_LOADED_MODELS: 동시에 메모리에 로드할 최대 모델 수
# 기본값: GPU에 따라 자동 (보통 1-3개)
# 멀티모델 라우팅 시 유용
OLLAMA_MAX_LOADED_MODELS=3 ollama serve

# OLLAMA_KEEP_ALIVE: 모델 메모리 유지 시간
# 기본값: 5m (5분), 0 = 즉시 언로드, -1 = 영구 유지
OLLAMA_KEEP_ALIVE="30m" ollama serve    # 30분 유지
OLLAMA_KEEP_ALIVE="0" ollama serve      # 즉시 언로드
OLLAMA_KEEP_ALIVE="-1" ollama serve     # 서버 종료까지 유지

# systemd 서비스 파일에서 영구 설정 (Linux)
sudo systemctl edit ollama
# [Service]
# Environment="OLLAMA_NUM_GPU=-1"
# Environment="OLLAMA_MAX_LOADED_MODELS=2"
# Environment="OLLAMA_KEEP_ALIVE=30m"

# API 호출 시 개별 모델에 keep_alive 설정
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "안녕하세요",
  "keep_alive": "10m"
}'
VRAM별 권장 설정
  • 4GB VRAM: OLLAMA_NUM_GPU=15~20 (Q4 양자화 7B 모델)
  • 8GB VRAM: OLLAMA_NUM_GPU=-1 (Q4 양자화 7B 전체 GPU)
  • 12-16GB VRAM: OLLAMA_NUM_GPU=-1 + Q6/Q8 양자화 또는 13B 모델
  • 24GB+ VRAM: 70B Q4 모델 전체 GPU 가능

메모리 최적화

python
# 1. 대화 히스토리 트리밍
def trim_messages(messages, max_tokens=2000):
    """오래된 메시지 제거하여 컨텍스트 제한"""
    total_tokens = 0
    trimmed = []

    # 최신 메시지부터 역순으로
    for msg in reversed(messages):
        msg_tokens = len(msg['content']) // 4  # 대략 추정
        if total_tokens + msg_tokens > max_tokens:
            break
        trimmed.insert(0, msg)
        total_tokens += msg_tokens

    # 시스템 메시지는 항상 유지
    if messages[0]['role'] == 'system':
        if trimmed[0]['role'] != 'system':
            trimmed.insert(0, messages[0])

    return trimmed

# 2. 모델 언로드 (메모리 확보)
import subprocess

def unload_ollama_model():
    # Ollama는 5분 후 자동 언로드 (기본값)
    # 즉시 언로드: 다른 모델 로드
    subprocess.run(['ollama', 'run', 'qwen2:1.5b', ''])

# 3. 스트리밍으로 메모리 절약
for chunk in ollama.chat(model='llama3.1:8b', messages=messages, stream=True):
    content = chunk['message']['content']
    print(content, end='')
    # 전체 응답을 메모리에 저장하지 않음

추론 최적화

최적화
// 1. Continuous Batching (vLLM)
# 여러 요청 동시 처리 (처리량 증가)
pip install vllm
python -m vllm.entrypoints.openai.api_server \
  --model TheBloke/Llama-3.1-8B-Instruct-GGUF \
  --port 8000 \
  --max-model-len 4096

// 2. KV 캐싱
# 이전 토큰의 key/value 재사용
# 대부분의 엔진에서 자동 활성화
# 긴 프롬프트 + 짧은 완성에 유리

// 3. Speculative Decoding
# 작은 모델로 예측 → 큰 모델로 검증
# 2-3배 속도 향상 (품질 동일)
# llama.cpp 지원
./main -m large.gguf -md small.gguf --draft 16

// 4. 병렬 디코딩
# 여러 시퀀스 동시 생성 (beam search)
# Text Generation WebUI
"num_beams": 4,
"length_penalty": 1.0

// 5. 조기 종료
# EOS 토큰 또는 최대 길이 도달 시 중단
"max_tokens": 100,
"stop": ["\n\n", "###", ""]

모델 선택 가이드

사용 사례별 권장

권장
// 1. 일반 대화 / 질의응답
✓ Llama 3.1 8B (균형잡힌 성능)
✓ Gemma 2 9B (Google, 빠름)
✓ Qwen 2.5 7B (한국어/중국어 우수)

// 2. 코드 생성
✓ DeepSeek Coder 33B (최고 품질)
✓ Code Llama 13B (범용)
✓ StarCoder 2 15B (다국어)

// 3. 한국어 중심
✓ Solar 10.7B (Upstage, 한국어 최적화)
✓ EEVE 10.8B (yanolja)
✓ Qwen 2.5 7B (한국어 지원 좋음)

// 4. 긴 컨텍스트 (32K+)
✓ Llama 3.1 8B/70B
✓ Qwen 2.5 (128K 지원)
✓ Yi 34B (200K 지원)

// 5. 임베딩 / RAG
✓ nomic-embed-text (Ollama 기본)
✓ bge-large-en (영어)
✓ bge-m3 (다국어)

// 6. 저사양 (8GB RAM 이하)
✓ Phi-3 Mini 3.8B (Microsoft, 소형이지만 강력)
✓ Qwen 2 1.5B (초경량)
✓ Llama 3.2 3B

// 7. 수학 / 추론
✓ Qwen 2.5 Math (수학 특화)
✓ Llama 3.1 70B (복잡한 추론)
✓ DeepSeek Math

// 8. 멀티모달 (이미지+텍스트)
✓ LLaVA 13B (Ollama: llava:13b)
✓ BakLLaVA 7B
✓ Obsidian 3B (경량)

결정 트리

결정
로컬 LLM 선택 플로우:

1. 하드웨어 확인
   ├─ 8GB RAM 미만 → Qwen 2 1.5B, Phi-3 Mini
   ├─ 8-16GB RAM → Llama 3.1 8B, Mistral 7B
   ├─ 16-32GB RAM → Llama 3.1 8B (Q8), Qwen 2.5 14B
   ├─ 32-64GB RAM → Llama 3.1 70B (Q4), Mixtral 8x7B
   └─ 64GB+ RAM → Llama 3.1 70B (Q8), Qwen 2.5 72B

2. GPU 유무
   ├─ CPU만 → 7B 이하 모델, Q4 양자화
   ├─ 8GB VRAM → 7B 모델, Q4/Q5 양자화
   ├─ 12-16GB VRAM → 13B 모델, Q4 양자화
   ├─ 24GB VRAM → 30B 모델 또는 70B (Q4)
   └─ 40GB+ VRAM → 70B 모델 (Q6/Q8)

3. 주 사용 언어
   ├─ 한국어 → Solar, EEVE, Qwen 2.5
   ├─ 영어 → Llama 3.1, Gemma 2
   ├─ 중국어 → Qwen 2.5, Yi
   └─ 다국어 → Llama 3.1, Gemma 2

4. 작업 유형
   ├─ 코딩 → DeepSeek Coder, Code Llama
   ├─ 수학 → Qwen Math, DeepSeek Math
   ├─ 일반 대화 → Llama 3.1, Gemma 2
   └─ 특수 도메인 → 파인튜닝 고려

5. 플랫폼 선택
   ├─ CLI 선호 → Ollama
   ├─ GUI 필요 → LM Studio
   ├─ 프로덕션 → LocalAI, vLLM
   └─ 실험 → Text Generation WebUI

모범 사례

모범 사례
// 1. 시작은 작게
• 3-7B 모델로 시작하여 워크플로우 확립
• 필요시 점진적으로 큰 모델 테스트
• 벤치마크보다 실제 작업 성능 중시

// 2. 양자화 실험
• Q4_K_M을 기본으로 시작
• 품질 부족 시 Q6_K 또는 Q8_0 시도
• 메모리 부족 시 Q4_0 또는 Q2_K

// 3. 프롬프트 최적화
• 모델별 프롬프트 템플릿 준수
• 시스템 프롬프트로 행동 명확히 정의
• Few-shot 예제로 품질 향상

// 4. 컨텍스트 관리
• 필요한 만큼만 컨텍스트 사용
• 긴 대화는 주기적으로 요약
• 슬라이딩 윈도우 기법 활용

// 5. 모니터링
• 토큰/초 속도 추적
• 메모리 사용량 모니터링
• 응답 품질 정기 평가

// 6. 보안
• 로컬 API는 localhost만 바인딩
• 외부 노출 시 인증 추가
• 민감한 데이터 로깅 주의

// 7. 업데이트
• 정기적으로 플랫폼 업데이트
• 새 모델 출시 시 테스트
• 커뮤니티 피드백 참고

// 8. 하이브리드 접근
• 간단한 작업 → 로컬 LLM
• 복잡한 작업 → 클라우드 API
• 비용과 품질 균형 유지

문제 해결

흔한 문제

문제
// 1. Out of Memory (OOM)
증상: 모델 로드 실패, 시스템 프리징
해결:
  • 더 작은 모델 또는 낮은 양자화 사용
  • GPU 레이어 수 줄이기 (--n-gpu-layers)
  • 배치 크기 감소
  • 컨텍스트 길이 제한

// 2. 느린 추론 속도
증상: 1-2 tok/s 이하
해결:
  • GPU 활용 확인 (nvidia-smi)
  • 더 공격적인 양자화 (Q4_0, Q2_K)
  • Metal/ROCm 등 가속 활성화
  • CPU 스레드 수 조정 (OLLAMA_NUM_THREADS)

// 3. 모델이 로드되지 않음
증상: "failed to load model" 오류
해결:
  • 모델 파일 경로 확인
  • 모델 파일 손상 여부 (재다운로드)
  • 호환되는 모델 형식인지 확인
  • 로그에서 구체적 오류 메시지 확인

// 4. 응답 품질 저하
증상: 무의미한 답변, 반복, 환각
해결:
  • 더 큰 모델 또는 높은 양자화 시도
  • 프롬프트 개선 (명확한 지시)
  • 생성 파라미터 조정 (temperature, repetition_penalty)
  • Few-shot 예제 추가

// 5. API 연결 실패
증상: "connection refused"
해결:
  • 서버 실행 여부 확인
  • 포트 번호 일치 여부
  • 방화벽/보안 그룹 설정
  • localhost vs 0.0.0.0 바인딩

// 6. CUDA/GPU 인식 안됨
증상: CPU로만 실행
해결:
  • NVIDIA 드라이버 업데이트
  • CUDA Toolkit 설치
  • GPU 지원 버전 설치 확인
  • nvidia-smi로 GPU 상태 확인

디버그 명령어

bash
# GPU 정보
nvidia-smi
# 또는 (AMD)
rocm-smi

# 메모리 사용량
free -h
htop

# Ollama 로그
journalctl -u ollama -f

# 프로세스별 GPU 사용
nvidia-smi pmon

# CUDA 버전
nvcc --version

# 포트 사용 확인
lsof -i :11434  # Ollama
lsof -i :1234   # LM Studio

# 모델 파일 검증
sha256sum model.gguf

추가 리소스

리소스
// 공식 문서
• Ollama: https://ollama.com/
• LM Studio: https://lmstudio.ai/
• LocalAI: https://localai.io/
• Text Gen WebUI: https://github.com/oobabooga/text-generation-webui
• vLLM: https://docs.vllm.ai/

// 모델 허브
• HuggingFace: https://huggingface.co/models
• Ollama Library: https://ollama.com/library
• TheBloke (GGUF): https://huggingface.co/TheBloke

// 커뮤니티
• r/LocalLLaMA (Reddit): 로컬 LLM 전문
• HuggingFace Forums: 기술 토론
• Ollama Discord: 실시간 지원

// 벤치마크
• Open LLM Leaderboard: https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard
• FastEval: 로컬 벤치마크 도구

// 튜토리얼
• "Running LLMs Locally" (YouTube 채널)
• Ollama Tutorials (공식)
• LoRA 파인튜닝 가이드
다음 단계
  • 다중 LLM 전환: 여러 LLM을 조합하여 비용과 품질 최적화
  • API 모범 사례: 프로덕션 환경의 에러 처리, 모니터링, 보안
  • 프롬프트 엔지니어링: 로컬 LLM에서 최고 품질 얻기

하드웨어 선택 가이드

로컬 LLM 실행에 적합한 하드웨어는 예산, 사용 사례, 모델 크기에 따라 다릅니다. 아래 의사결정 트리를 참고하여 최적의 하드웨어를 선택하세요.

하드웨어 선택 가이드 의사결정 트리 플랫폼 선택 사용 가능한 하드웨어는? Apple Silicon M1/M2/M3/M4 시리즈 8GB 통합메모리 7B Q4 모델 Phi-3, Qwen 1.5B 16-64GB 통합 13B~70B 모델 Metal 가속 우수 NVIDIA GPU CUDA 지원 데스크탑/서버 8-12GB 7-13B Q4 RTX 3060/4060 24GB+ 70B Q4 가능 RTX 4090/A6000 CPU 전용 GPU 없는 서버/노트북 8-16GB 3-7B Q4 느리지만 작동 32GB+ 13B Q4 가능 AVX2 권장 플랫폼별 권장 솔루션 Apple Silicon 추천 Ollama + Metal 가속 LM Studio (GUI) 통합메모리로 대형 모델 유리 NVIDIA GPU 추천 vLLM (프로덕션) Ollama / LocalAI CUDA 가속으로 최고 성능 CPU 전용 추천 Ollama (Q4 양자화) 경량 모델 (3-7B) AVX2 지원 CPU 필수 VRAM/통합메모리 = 모델 크기를 결정하는 가장 중요한 요소 최소 8GB RAM/VRAM | 권장 16GB 이상

그림 12: 하드웨어 선택 가이드 의사결정 트리 - 플랫폼과 메모리 기반 모델 크기 권장

하드웨어 투자 우선순위
  • 1순위 - VRAM/메모리: 모델 크기를 직접 결정합니다. 24GB VRAM이면 대부분의 모델 실행 가능
  • 2순위 - 메모리 대역폭: 토큰 생성 속도에 직접 영향. Apple Silicon의 통합메모리가 유리
  • 3순위 - 연산 성능: 프롬프트 처리(prefill) 속도에 영향. CUDA 코어/텐서 코어가 핵심

모델 형식 비교

로컬 LLM을 실행할 때는 모델 형식에 따라 지원되는 플랫폼과 성능이 다릅니다. 아래 표에서 주요 모델 형식의 특성을 비교합니다.

형식 양자화 지원 플랫폼 장점 단점
GGUF Q2~Q8, FP16 Ollama, LM Studio, llama.cpp, LocalAI CPU+GPU 혼합 실행, 범용성 최고, 단일 파일 GPU 전용 대비 약간 느림
GPTQ 2~8bit (PTQ) Text Gen WebUI, vLLM, HuggingFace GPU 추론 최적화, 높은 품질 유지 GPU 필수, 양자화 시간 김
AWQ 4bit 중심 vLLM, Text Gen WebUI, HuggingFace GPTQ보다 빠른 추론, 높은 품질 지원 모델 적음, GPU 필수
SafeTensors FP16/BF16/FP32 HuggingFace, vLLM, Text Gen WebUI 안전한 직렬화, 파인튜닝 용이 양자화 미지원 (원본 크기)
형식 선택 가이드
  • CPU 또는 CPU+GPU 혼합: GGUF (Ollama, LM Studio)
  • GPU 전용 추론: AWQ > GPTQ (vLLM, Text Gen WebUI)
  • 파인튜닝/학습: SafeTensors (HuggingFace Transformers)
  • 범용적 사용: GGUF Q4_K_M이 가장 무난한 선택

보안 설정

로컬 LLM을 운영할 때 보안은 종종 간과되지만, 특히 네트워크에 노출하거나 프로덕션 환경에서 운영할 때는 필수적인 고려사항입니다.

네트워크 격리

bash
# 1. localhost만 바인딩 (기본값, 권장)
# Ollama는 기본적으로 127.0.0.1만 수신
OLLAMA_HOST="127.0.0.1:11434" ollama serve

# 2. 외부 접근 허용 시 (주의 필요)
OLLAMA_HOST="0.0.0.0:11434" ollama serve

# 3. Docker 네트워크 격리
docker run -d \
  --network="host" \      # 또는 별도 브릿지 네트워크
  -p 127.0.0.1:11434:11434 \  # localhost만 바인딩
  ollama/ollama

# 4. LM Studio: 설정에서 서버 바인딩 주소 지정
# Server → Network → Listen Address: 127.0.0.1

API 인증 및 접근 제어

python
# Nginx 리버스 프록시를 통한 API 키 인증
# /etc/nginx/conf.d/llm-proxy.conf

# upstream llm_backend {
#     server 127.0.0.1:11434;
# }
# 
# server {
#     listen 8443 ssl;
# 
#     # API 키 검증
#     if ($http_authorization != "Bearer YOUR_SECRET_KEY") {
#         return 401;
#     }
# 
#     location / {
#         proxy_pass http://llm_backend;
#     }
# }

# Python 미들웨어 예제 (FastAPI)
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import httpx

app = FastAPI()
security = HTTPBearer()
VALID_KEYS = {"sk-local-key-001", "sk-local-key-002"}

async def verify_key(creds: HTTPAuthorizationCredentials = Depends(security)):
    if creds.credentials not in VALID_KEYS:
        raise HTTPException(status_code=401, detail="유효하지 않은 API 키")
    return creds.credentials

@app.post("/v1/chat/completions")
async def proxy_chat(request: dict, key: str = Depends(verify_key)):
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            "http://127.0.0.1:11434/v1/chat/completions",
            json=request
        )
        return resp.json()

방화벽 규칙

bash
# UFW (Ubuntu/Debian)
# 기본 정책: 외부에서 LLM 포트 차단
sudo ufw deny 11434
sudo ufw deny 1234
sudo ufw deny 8080

# 특정 IP만 허용 (팀 내부 접근)
sudo ufw allow from 192.168.1.0/24 to any port 11434

# iptables (고급 설정)
# LLM API 포트를 내부 네트워크만 허용
sudo iptables -A INPUT -p tcp --dport 11434 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 11434 -j DROP

# Docker 방화벽 (Docker는 UFW를 우회할 수 있음)
# /etc/docker/daemon.json
# { "iptables": false }
# 또는 포트 바인딩 시 127.0.0.1 명시
docker run -p 127.0.0.1:8080:8080 localai/localai
보안 체크리스트
  • 로컬 API 서버는 반드시 127.0.0.1에 바인딩 (기본값 확인)
  • 외부 노출 시 리버스 프록시 + API 키 인증 필수
  • 프롬프트 인젝션 방어를 위한 입력 검증 구현
  • 모델 파일의 출처 확인 (HuggingFace 공식 저장소 권장)
  • 로그에 민감한 프롬프트/응답이 기록되지 않도록 설정
  • 정기적으로 Ollama/LM Studio 등 플랫폼 보안 업데이트 적용

핵심 정리

  • 로컬 LLM API 활용의 핵심 개념과 흐름을 정리합니다.
  • 로컬 LLM의 장점과 단점를 단계별로 이해합니다.
  • 실전 적용 시 기준과 주의점을 확인합니다.

실무 팁

  • 입력/출력 예시를 고정해 재현성을 확보하세요.
  • 로컬 LLM API 활용 범위를 작게 잡고 단계적으로 확장하세요.
  • 로컬 LLM의 장점과 단점 조건을 문서화해 대응 시간을 줄이세요.