로컬 AI 개발 환경 구축 — GPU 없이 LLM 돌리기
Ollama, LM Studio, llama.cpp 설치와 사용법, GGUF 양자화 모델 선택, Apple Silicon MLX, RAM 요구사항, OpenAI SDK 호환 REST API, LangChain 연동.
한 줄 요약: Ollama, LM Studio, llama.cpp로 GPU 없이 로컬에서 LLM을 실행할 수 있다. Apple Silicon Mac 기준 7B 모델은 8GB RAM, 13B는 16GB RAM이면 실용적인 속도로 추론이 가능하다.
- 외부 API(OpenAI, Anthropic) 없이 로컬에서 LLM을 실행하고 개발에 활용하고 싶은 개발자
- 프라이버시 또는 비용 이유로 클라우드 AI API 사용을 피하고 싶은 경우
- Apple Silicon Mac 또는 일반 CPU 서버에서 LLM을 돌려보고 싶은 개발자
- Ollama, LM Studio, llama.cpp 중 자신에게 맞는 도구를 선택하고 싶은 경우
로컬 LLM 실행 도구 비교 — Ollama, LM Studio, llama.cpp
로컬 LLM 실행 도구는 크게 세 가지로 나뉜다. 목적과 기술 수준에 따라 선택이 달라진다.
| 도구 | 특징 | 적합 대상 | API 서버 |
|---|---|---|---|
| Ollama | CLI + REST API 서버, 모델 관리 간단 | 개발자, API 통합 | 기본 제공 (OpenAI 호환) |
| LM Studio | GUI, 모델 다운로드/채팅 UI 내장 | 비개발자 포함 범용 | 로컬 서버 제공 |
| llama.cpp | C++ 원본, 최고 성능, 최대 커스텀 | 성능 최적화, 서버 배포 | llama-server 포함 |
개발 통합 목적이라면 Ollama가 가장 빠른 시작점이다. GUI가 필요하거나 비개발자와 함께 쓴다면 LM Studio, 성능과 커스텀이 최우선이라면 llama.cpp 직접 빌드가 적합하다.
Ollama 설치와 기본 사용
Ollama는 Docker처럼 모델을 pull·run 명령으로 관리하는 로컬 LLM 실행 환경이다. macOS, Linux, Windows(WSL2) 모두 지원하며, OpenAI 호환 REST API 서버를 기본으로 제공한다.
Ollama 설치 및 기본 명령# macOS/Linux 설치 curl -fsSL https://ollama.com/install.sh | sh # Windows: https://ollama.com/download 에서 설치 파일 다운로드 # 모델 실행 (없으면 자동 다운로드) ollama run llama3.2 # Meta Llama 3.2 3B (2GB) ollama run llama3.2:1b # 경량 1B 버전 (1.3GB) ollama run qwen2.5:7b # Alibaba Qwen 2.5 7B (4.7GB) ollama run gemma3:9b # Google Gemma 3 9B (5.6GB) ollama run mistral:7b # Mistral 7B (4.1GB) ollama run deepseek-r1:7b # DeepSeek-R1 7B (4.7GB) # 모델 목록 확인 ollama list # 모델 삭제 ollama rm llama3.2 # 백그라운드 서버 실행 (기본: localhost:11434) ollama serve # REST API 호출 (curl) curl http://localhost:11434/api/chat -d '{ "model": "llama3.2", "messages": [{"role": "user", "content": "TypeScript 제네릭을 설명해줘"}], "stream": false }' # OpenAI 호환 엔드포인트 (drop-in replacement) curl http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" -d '{ "model": "llama3.2", "messages": [{"role": "user", "content": "hello"}] }'
양자화 모델(GGUF) 선택 가이드
GGUF(GPT-Generated Unified Format)는 llama.cpp 진영에서 사용하는 모델 파일 형식이다. 양자화(quantization)는 모델의 부동소수점 가중치를 더 낮은 비트로 압축해 메모리 사용량과 추론 속도를 개선하는 기술이다.
양자화 레벨과 특성:
| 양자화 | 비트 | 7B 모델 크기 | 품질 손실 | 추천 용도 |
|---|---|---|---|---|
| Q2_K | 2bit | ~2.8GB | 높음 | RAM 4GB 이하 극한 절약 |
| Q4_0 | 4bit | ~3.8GB | 보통 | 속도 최우선 |
| Q4_K_M | 4bit | ~4.1GB | 낮음 | 8GB RAM 환경 기본 추천 |
| Q5_K_M | 5bit | ~4.8GB | 매우 낮음 | 품질·속도 균형, 16GB RAM |
| Q8_0 | 8bit | ~7.2GB | 거의 없음 | 최고 품질, 16GB+ RAM |
| F16 | 16bit (원본) | ~13.5GB | 없음 | 32GB+ RAM, GPU 환경 |
대부분의 로컬 개발 환경에서 Q4_K_M이 최적점이다. Ollama는 내부적으로 GGUF를 사용하며 모델 페이지에서 양자화 레벨을 태그로 선택할 수 있다.
Apple Silicon — Metal GPU와 MLX 프레임워크
Apple Silicon(M1/M2/M3/M4 시리즈)은 CPU와 GPU가 동일한 메모리를 공유하는 통합 메모리(Unified Memory) 구조다. 이 덕분에 별도 GPU 메모리 없이 RAM 전체를 GPU 컴퓨팅에 활용할 수 있다. 결과적으로 NVIDIA GPU 없이도 로컬 LLM을 실용적인 속도로 실행할 수 있는 플랫폼이다.
Ollama의 Apple Silicon 최적화: Ollama는 macOS에서 Metal(Apple GPU API)을 자동으로 사용한다. 별도 설정 없이 설치만 하면 GPU 가속이 활성화된다.
MLX (Apple Machine Learning eXchange): Apple이 2023년 공개한 Apple Silicon 전용 ML 프레임워크다. NumPy와 유사한 API를 제공하며, Apple Silicon에서 llama.cpp보다 높은 토큰 생성 속도를 보이는 경우가 있다.
MLX — Apple Silicon에서 LLM 실행# MLX LM 설치 (Python 3.11+, macOS Apple Silicon 전용) pip install mlx-lm # Hugging Face에서 MLX 변환 모델 실행 python -m mlx_lm.generate --model mlx-community/Llama-3.2-3B-Instruct-4bit --prompt "Rust의 소유권 개념을 설명해줘" # 대화 모드 python -m mlx_lm.chat --model mlx-community/Qwen2.5-7B-Instruct-4bit # 서버 모드 (OpenAI 호환 API) python -m mlx_lm.server --model mlx-community/Llama-3.2-3B-Instruct-4bit --port 8080 # 성능 참고 (M3 Pro 18GB 기준, 4bit 양자화) # Llama 3.2 3B: ~80 tokens/sec # Qwen 2.5 7B: ~40 tokens/sec # Llama 3.1 8B: ~35 tokens/sec
llama.cpp 직접 빌드 — 최고 성능 최적화
llama.cpp는 Georgi Gerganov가 Meta LLaMA를 C++로 이식한 프로젝트다. GGUF 형식의 원본 런타임이며, Ollama, LM Studio 모두 내부적으로 llama.cpp를 사용한다. 직접 빌드하면 컴파일 옵션으로 특정 하드웨어를 최적화할 수 있다.
llama.cpp 빌드 및 서버 실행# 소스 클론 git clone https://github.com/ggerganov/llama.cpp cd llama.cpp # macOS Apple Silicon (Metal GPU 가속) cmake -B build -DGGML_METAL=ON cmake --build build --config Release -j$(nproc) # Linux CUDA (NVIDIA GPU) cmake -B build -DGGML_CUDA=ON cmake --build build --config Release -j$(nproc) # Linux CPU 전용 (AVX2 최적화) cmake -B build -DGGML_AVX2=ON cmake --build build --config Release -j$(nproc) # GGUF 모델 다운로드 (Hugging Face CLI) pip install huggingface_hub huggingface-cli download bartowski/Llama-3.2-3B-Instruct-GGUF Llama-3.2-3B-Instruct-Q4_K_M.gguf --local-dir ./models # HTTP 서버 실행 (OpenAI 호환) ./build/bin/llama-server --model ./models/Llama-3.2-3B-Instruct-Q4_K_M.gguf --port 8080 --ctx-size 4096 --n-gpu-layers 99 --parallel 4 # 직접 추론 (CLI) ./build/bin/llama-cli -m ./models/Llama-3.2-3B-Instruct-Q4_K_M.gguf -p "TypeScript 제네릭을 코드 예시와 함께 설명해줘" -n 512
개발 환경 통합 — REST API와 LangChain 연동
Ollama와 llama-server 모두 OpenAI 호환 API를 제공하므로 기존 OpenAI SDK를 그대로 사용할 수 있다. baseURL만 로컬 주소로 바꾸면 된다.
TypeScript — OpenAI SDK로 Ollama 연동import OpenAI from 'openai' // baseURL만 변경 — 나머지 코드는 동일 const client = new OpenAI({ baseURL: 'http://localhost:11434/v1', apiKey: 'ollama', // 값은 무관, 필드는 필요 }) async function chat(prompt: string): Promise<string> { const response = await client.chat.completions.create({ model: 'llama3.2', messages: [ { role: 'system', content: '당신은 시니어 TypeScript 개발자입니다.' }, { role: 'user', content: prompt } ], temperature: 0.7, max_tokens: 1024, }) return response.choices[0].message.content ?? '' } // 스트리밍 async function streamChat(prompt: string) { const stream = await client.chat.completions.create({ model: 'llama3.2', messages: [{ role: 'user', content: prompt }], stream: true, }) for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? '') } }
Python — LangChain + Ollama 연동from langchain_ollama import ChatOllama from langchain_core.messages import HumanMessage, SystemMessage from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate # 기본 사용 llm = ChatOllama(model='llama3.2', temperature=0.7) response = llm.invoke([ SystemMessage(content='당신은 코드 리뷰 전문가입니다.'), HumanMessage(content='이 함수를 리뷰해주세요: def add(a, b): return a + b'), ]) print(response.content) # 체인 구성 prompt = ChatPromptTemplate.from_messages([ ('system', '당신은 {role}입니다.'), ('human', '{question}'), ]) chain = prompt | llm | StrOutputParser() result = chain.invoke({ 'role': '시니어 백엔드 개발자', 'question': 'REST API와 GraphQL의 차이를 설명해줘', }) print(result)
8GB RAM: 7B 모델 Q4_K_M까지 실용적 (20~30 tok/sec, Apple Silicon)
16GB RAM: 13B 모델 Q4_K_M 또는 7B Q8_0 (10~20 tok/sec)
32GB RAM: 34B 모델 Q4_K_M 또는 13B F16 수준
64GB+ RAM: 70B 모델 Q4_K_M 가능 (5~10 tok/sec)