로컬 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 솔루션의 특성을 한눈에 비교합니다. 각 솔루션의 인터페이스 유형, 난이도, 성능 수준을 확인하세요.
그림 8: 5가지 로컬 LLM 솔루션 비교 - 인터페이스, 난이도, 성능 수준을 한눈에 파악
로컬 LLM의 장점과 단점
그림 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 기반 워크플로우를 제공합니다.
그림 9: Ollama 내부 아키텍처 - CLI에서 하드웨어까지 4계층 구조
설치
# 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
그림 11: 모델 양자화 파이프라인 - FP16에서 Q2_K까지 품질과 용량의 트레이드오프. Q4_K_M이 성능/용량 균형에서 권장
Ollama API 사용
# 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)
# 기본 요청
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: 커스텀 프롬프트, 파라미터 설정
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 재귀와 반복문 두 가지 방식으로 구현하겠습니다...
# 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 호환)
# 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 기반 코드를 수정 없이 로컬 모델로 전환할 수 있습니다.
그림 10: OpenAI 호환 API 게이트웨이 - base_url만 변경하면 동일한 코드로 다양한 로컬 LLM 백엔드 사용 가능
# 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 백엔드:
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 백엔드:
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 백엔드:
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로 한번에 구성할 수 있습니다.
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:
# 서비스 시작
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
LocalAI
LocalAI는 OpenAI API와 완벽히 호환되는 오픈소스 프로젝트로, 다양한 모델 형식(GGUF, GGML, PyTorch)을 지원합니다.
Docker로 설치
# 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)
# 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 사용
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"
)
고급 기능
// 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 플랫폼입니다.
설치
# 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 사용
# 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
}'
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 필수)
✗ 설치 및 설정 복잡 (초보자에게 어려움)
설치
# 필수 요구사항
# - 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 이상 권장
기본 사용법
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 서버
# 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
클라이언트 사용
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}")
고급 기능
# 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"
프로덕션 배포
# 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
# 프로덕션 클라이언트 (에러 처리, 재시도)
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이 제한된 환경에서는 이 설정들이 핵심적인 역할을 합니다.
# 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"
}'
- 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 가능
메모리 최적화
# 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 상태 확인
디버그 명령어
# 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 실행에 적합한 하드웨어는 예산, 사용 사례, 모델 크기에 따라 다릅니다. 아래 의사결정 트리를 참고하여 최적의 하드웨어를 선택하세요.
그림 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을 운영할 때 보안은 종종 간과되지만, 특히 네트워크에 노출하거나 프로덕션 환경에서 운영할 때는 필수적인 고려사항입니다.
네트워크 격리
# 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 인증 및 접근 제어
# 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()
방화벽 규칙
# 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의 장점과 단점 조건을 문서화해 대응 시간을 줄이세요.