로컬 LLM 실행 가이드 — Ollama, llama.cpp, vLLM

로컬 LLM이 필요한 이유

클라우드 API는 편리하지만 비용, 프라이버시, 인터넷 의존성이라는 제약이 있습니다. 로컬 LLM은 내 컴퓨터에서 직접 AI 모델을 실행하는 것입니다. 집에 커피 머신을 두는 것과 같습니다. 카페에 갈 필요 없이, 원할 때 바로 내가 원하는 커피를 만들 수 있습니다.

로컬 LLM의 주요 장점:

장점설명
비용 절감API 호출 비용 없음 (전기료만)
프라이버시데이터가 외부로 전송되지 않음
오프라인 사용인터넷 없이도 동작
커스터마이징파인튜닝, 프롬프트 자유
지연 시간네트워크 지연 없음

도구별 비교

항목Ollamallama.cppvLLM
난이도매우 쉬움중간중간
설치원클릭 설치컴파일 필요pip install
GPU 필수아니오아니오권장 (CUDA)
API 서버내장 (OpenAI 호환)별도 설정내장
양자화 지원GGUFGGUF (핵심 기능)AWQ, GPTQ
배치 처리제한적제한적우수 (PagedAttention)
적합한 용도개인 개발, 실험임베디드, 최적화프로덕션 서빙

Ollama: 가장 쉬운 시작

Ollama는 Docker처럼 pullrun 명령으로 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 기준)품질속도
FP1616bit~14GB최고느림
Q8_08bit~7GB매우 좋음보통
Q5_K_M5bit~5GB좋음빠름
Q4_K_M4bit~4GB양호빠름
Q3_K_M3bit~3GB다소 저하매우 빠름
Q2_K2bit~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)8GBLlama 3.2 1B (Q4)Ollama
데스크톱 (16GB RAM)16GBLlama 3.2 3B (Q5)Ollama
데스크톱 (32GB RAM)32GBLlama 3.1 8B (Q5)Ollama, llama.cpp
RTX 3060 (12GB)12GB VRAMLlama 3.1 8B (Q4)Ollama (GPU)
RTX 4090 (24GB)24GB VRAMLlama 3.1 70B (Q4)vLLM
A100 (80GB)80GB VRAMLlama 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 등의 사용자가 다양한 양자화 버전을 올려두고 있습니다.

이 글이 도움이 되었나요?