로컬 LLM이 필요한 이유
클라우드 API는 편리하지만 비용, 프라이버시, 인터넷 의존성이라는 제약이 있습니다. 로컬 LLM은 내 컴퓨터에서 직접 AI 모델을 실행하는 것입니다. 집에 커피 머신을 두는 것과 같습니다. 카페에 갈 필요 없이, 원할 때 바로 내가 원하는 커피를 만들 수 있습니다.
로컬 LLM의 주요 장점:
| 장점 | 설명 |
|---|---|
| 비용 절감 | API 호출 비용 없음 (전기료만) |
| 프라이버시 | 데이터가 외부로 전송되지 않음 |
| 오프라인 사용 | 인터넷 없이도 동작 |
| 커스터마이징 | 파인튜닝, 프롬프트 자유 |
| 지연 시간 | 네트워크 지연 없음 |
도구별 비교
| 항목 | Ollama | llama.cpp | vLLM |
|---|---|---|---|
| 난이도 | 매우 쉬움 | 중간 | 중간 |
| 설치 | 원클릭 설치 | 컴파일 필요 | pip install |
| GPU 필수 | 아니오 | 아니오 | 권장 (CUDA) |
| API 서버 | 내장 (OpenAI 호환) | 별도 설정 | 내장 |
| 양자화 지원 | GGUF | GGUF (핵심 기능) | AWQ, GPTQ |
| 배치 처리 | 제한적 | 제한적 | 우수 (PagedAttention) |
| 적합한 용도 | 개인 개발, 실험 | 임베디드, 최적화 | 프로덕션 서빙 |
Ollama: 가장 쉬운 시작
Ollama는 Docker처럼 pull과 run 명령으로 LLM을 관리합니다. macOS, Linux, Windows 모두 지원합니다.
설치 및 기본 사용
# macOS/Linux 설치
curl -fsSL https://ollama.ai/install.sh | sh
# 모델 다운로드 및 실행
ollama pull llama3.2 # 모델 다운로드 (3B, 약 2GB)
ollama run llama3.2 # 대화 모드 실행
# 모델 목록 확인
ollama list
# NAME SIZE MODIFIED
# llama3.2:latest 2.0 GB 2 minutes ago
# gemma2:2b 1.6 GB 1 hour ago
# 모델 삭제
ollama rm gemma2:2b
API 서버로 활용
Ollama는 OpenAI 호환 API를 기본 제공합니다. 기존 OpenAI SDK 코드를 거의 수정 없이 사용할 수 있습니다.
# pip install openai
from openai import OpenAI
# Ollama 로컬 서버에 연결 (기본 포트: 11434)
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama" # Ollama는 인증 불필요, 아무 값이나 가능
)
# ChatCompletion 호출 (OpenAI API와 동일한 인터페이스)
response = client.chat.completions.create(
model="llama3.2",
messages=[
{"role": "system", "content": "한국어로 답변하세요."},
{"role": "user", "content": "Python 리스트 컴프리헨션을 설명해주세요."}
],
temperature=0.7,
max_tokens=500
)
print(response.choices[0].message.content)
# 출력: 리스트 컴프리헨션은 기존 리스트를 기반으로 새 리스트를 생성하는
# Python의 간결한 문법입니다...
# 스트리밍 응답
stream = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Hello"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
Modelfile로 커스텀 모델
# Modelfile — 커스텀 모델 정의
FROM llama3.2
# 시스템 프롬프트 설정
SYSTEM """
당신은 Python 코딩 전문가입니다.
코드에는 반드시 한국어 주석을 포함하세요.
간결하고 실용적인 답변을 제공하세요.
"""
# 파라미터 조정
PARAMETER temperature 0.3
PARAMETER top_p 0.9
PARAMETER num_ctx 4096
# 커스텀 모델 빌드 및 실행
ollama create python-expert -f Modelfile
ollama run python-expert
# >>> 피보나치 함수 작성해줘
# def fibonacci(n):
# """n번째 피보나치 수를 반환합니다."""
# ...
llama.cpp: 최적화의 끝판왕
llama.cpp는 C/C++로 작성된 LLM 추론 엔진으로, CPU 전용 환경에서도 최적의 성능을 발휘합니다. 양자화(Quantization)를 통해 모델 크기를 대폭 줄일 수 있습니다.
양자화 수준 비교
| 양자화 | 비트 | 모델 크기 (7B 기준) | 품질 | 속도 |
|---|---|---|---|---|
| FP16 | 16bit | ~14GB | 최고 | 느림 |
| Q8_0 | 8bit | ~7GB | 매우 좋음 | 보통 |
| Q5_K_M | 5bit | ~5GB | 좋음 | 빠름 |
| Q4_K_M | 4bit | ~4GB | 양호 | 빠름 |
| Q3_K_M | 3bit | ~3GB | 다소 저하 | 매우 빠름 |
| Q2_K | 2bit | ~2.5GB | 상당히 저하 | 매우 빠름 |
# llama.cpp 빌드 (CPU 전용)
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make -j$(nproc)
# CUDA GPU 지원 빌드
make -j$(nproc) GGML_CUDA=1
# GGUF 모델 다운로드 (Hugging Face에서)
# 예: TheBloke/Llama-2-7B-Chat-GGUF 에서 Q4_K_M 버전
# 실행 (텍스트 생성)
./llama-cli \
-m models/llama-3.2-3b-q4_k_m.gguf \
-p "Python에서 데코레이터란" \
-n 256 \ # 최대 생성 토큰 수
-t 8 \ # CPU 스레드 수
--temp 0.7
# 출력: Python에서 데코레이터란 함수를 감싸는 함수로...
# API 서버 실행
./llama-server \
-m models/llama-3.2-3b-q4_k_m.gguf \
--host 0.0.0.0 \
--port 8080
# OpenAI 호환 API가 http://localhost:8080 에서 실행됩니다
vLLM: 프로덕션 서빙
vLLM은 고처리량(high-throughput) LLM 서빙에 최적화된 엔진입니다. PagedAttention 알고리즘으로 GPU 메모리를 효율적으로 관리하여, 동시 요청 처리 성능이 뛰어납니다.
# vLLM 설치 (CUDA GPU 필요)
pip install vllm
# API 서버 실행 (OpenAI 호환)
vllm serve meta-llama/Llama-3.2-3B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9
# vLLM 서버에 요청 (OpenAI SDK 사용)
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="token-placeholder"
)
# 단일 요청
response = client.chat.completions.create(
model="meta-llama/Llama-3.2-3B-Instruct",
messages=[{"role": "user", "content": "REST API 설계 원칙 3가지"}],
max_tokens=300
)
print(response.choices[0].message.content)
# 배치 처리 (vLLM의 강점 — 높은 처리량)
import asyncio
from openai import AsyncOpenAI
async_client = AsyncOpenAI(
base_url="http://localhost:8000/v1",
api_key="token-placeholder"
)
async def batch_inference(prompts: list[str]):
"""여러 프롬프트를 동시에 처리합니다."""
tasks = [
async_client.chat.completions.create(
model="meta-llama/Llama-3.2-3B-Instruct",
messages=[{"role": "user", "content": p}],
max_tokens=200
)
for p in prompts
]
# 동시에 요청 전송 — vLLM이 내부적으로 배치 처리
results = await asyncio.gather(*tasks)
return [r.choices[0].message.content for r in results]
prompts = ["Python이란?", "JavaScript란?", "Rust란?"]
answers = asyncio.run(batch_inference(prompts))
for p, a in zip(prompts, answers):
print(f"Q: {p}\nA: {a}\n")
하드웨어별 모델 선택 가이드
| 하드웨어 | RAM/VRAM | 추천 모델 | 도구 |
|---|---|---|---|
| 노트북 (8GB RAM) | 8GB | Llama 3.2 1B (Q4) | Ollama |
| 데스크톱 (16GB RAM) | 16GB | Llama 3.2 3B (Q5) | Ollama |
| 데스크톱 (32GB RAM) | 32GB | Llama 3.1 8B (Q5) | Ollama, llama.cpp |
| RTX 3060 (12GB) | 12GB VRAM | Llama 3.1 8B (Q4) | Ollama (GPU) |
| RTX 4090 (24GB) | 24GB VRAM | Llama 3.1 70B (Q4) | vLLM |
| A100 (80GB) | 80GB VRAM | Llama 3.1 70B (FP16) | vLLM |
실전 팁
- Ollama부터 시작하세요: 설치 5분이면 LLM을 실행할 수 있습니다. 나중에 필요에 따라 llama.cpp나 vLLM으로 전환하세요.
- Q4_K_M 양자화를 기본으로 사용하세요: 품질과 크기의 균형이 가장 좋습니다. 품질이 부족하면 Q5_K_M으로 올리세요.
- 컨텍스트 길이에 주의하세요: 로컬 모델은 컨텍스트 길이가 제한적입니다.
num_ctx설정으로 조절하되, 길이가 늘면 메모리 사용량도 증가합니다. - GPU가 있다면 반드시 활용하세요: CPU 대비 5~20배 빠릅니다. Ollama는 GPU를 자동 감지하고, llama.cpp는
GGML_CUDA=1로 빌드해야 합니다. - 모델 크기보다 양자화 품질이 중요합니다: 70B Q2보다 8B Q5가 더 나은 결과를 보이는 경우가 많습니다.
- Hugging Face의 GGUF 포맷을 찾으세요:
TheBloke,bartowski등의 사용자가 다양한 양자화 버전을 올려두고 있습니다.