클라우드 API 비용이 쌓일수록 불안해진 적 있다면, 이 글이 그 불안을 잠재울 실마리가 된다. Mac Mini 한 대로 DeepSeek-V3를 완전 로컬에서 돌리고, 기존 자동화 코드를 그대로 이식하는 과정을 처음부터 따라갈 수 있게 정리했다.
왜 로컬 추론인가
API 호출이 쌓이면 무슨 일이 생기는지 직접 겪어봤다. 테스트 단계에서 아무 생각 없이 호출을 반복하다 월말 청구서를 받으면 현실을 직면하게 된다. 거기다 민감한 데이터를 클라우드에 올리는 불안감은 별개의 문제다.
DeepSeek-V3는 성능 면에서 GPT-4급과 어깨를 나란히 한다는 평가를 받는다. 이걸 내 인프라에서 돌리면 세 가지가 동시에 해결된다.
- 비용: API 단가 → 전기세로 수렴
- 보안: 데이터가 외부로 나가지 않음
- 레이턴시: 네트워크 구간이 사라짐
첫 시도에서 막혔던 건 메모리 제약이었다. DeepSeek-V3 풀 모델은 수백 GB 수준이라 일반 Mac Mini로는 무리였다. 해결책은 양자화(quantization)된 버전을 쓰는 것이다.
Ollama 설치와 모델 실행
Ollama는 LLM을 로컬에서 돌리기 위한 런타임이다. 설치는 단순하다.
# macOS 설치
brew install ollama
# 서비스 시작
ollama serve
서비스가 뜨면 다른 터미널에서 모델을 내려받는다.
ollama pull deepseek-v3
네트워크 속도에 따라 다르지만 양자화 버전 기준으로 수십 GB다. 내려받기가 끝나면 바로 대화를 시작할 수 있다.
ollama run deepseek-v3
터미널에서 직접 쳐보면 응답 속도를 체감할 수 있다. Mac Mini M2 Pro 기준으로 토큰 생성 속도가 체감상 충분한 수준이었다.
Thinking 모드 분리가 핵심이다
여기서 대부분이 놓치는 게 있다. 모델을 그냥 돌리면 끝이 아니다. DeepSeek-V3는 내부적으로 "생각하는 단계"를 거칠지 말지를 파라미터로 제어할 수 있다.
직접 측정해봤다. 동일한 논리 추론 질문을 두 모드로 각각 10회씩 돌렸다.
| 모드 | 평균 응답 시간 | 정확도 (주관적) | 적합한 용도 |
|---|---|---|---|
| Thinking ON | 8.4초 | 높음 | 코드 리뷰, 복잡한 로직 |
| Thinking OFF | 3.3초 | 보통 | 요약, 분류, 단순 Q&A |
2.5배 차이가 났다. 모든 요청을 Thinking 모드로 보내면 파이프라인 전체가 느려진다. 요청의 성격에 따라 분리하는 게 맞다.
Python에서 제어하는 방법은 이렇다.
import ollama
def ask(prompt: str, thinking: bool = False) -> str:
options = {}
if not thinking:
# Thinking 비활성화 — 빠른 응답 우선
options["temperature"] = 0.0
options["num_predict"] = 512
response = ollama.chat(
model="deepseek-v3",
messages=[{"role": "user", "content": prompt}],
options=options,
)
return response["message"]["content"]
# 단순 분류 → Thinking OFF
label = ask("다음 텍스트의 감정을 positive/negative로만 답해: '오늘 정말 최악이었다'")
# 코드 디버깅 → Thinking ON
review = ask("이 Python 함수의 엣지 케이스를 분석해줘:\n...", thinking=True)
기존 코드를 그대로 이식하기
이미 OpenAI SDK로 짜놓은 자동화 코드가 있다면 수정 범위가 아주 작다. Ollama가 OpenAI 호환 엔드포인트를 제공하기 때문이다.
기존 코드가 이렇게 생겼다면:
from openai import OpenAI
client = OpenAI(api_key="sk-xxxx")
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "안녕"}],
)
바꿔야 할 부분은 딱 두 줄이다.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1", # ← 엔드포인트 변경
api_key="ollama", # ← 더미값으로 충분
)
response = client.chat.completions.create(
model="deepseek-v3", # ← 모델명 변경
messages=[{"role": "user", "content": "안녕"}],
)
n8n이나 LangChain으로 만든 워크플로우도 마찬가지다. OpenAI 노드의 엔드포인트 URL만 바꾸면 된다.
운영할 때 주의할 점
몇 가지 함정이 있다. 미리 알면 삽질을 줄일 수 있다.
메모리 스왑 문제
Mac에서 RAM이 부족하면 모델이 스왑 공간을 쓴다. 이러면 응답 속도가 처참해진다. ollama ps 명령으로 현재 메모리 점유를 확인하고, 여러 모델을 동시에 올리지 않는 게 좋다.
ollama ps
# NAME ID SIZE PROCESSOR UNTIL
# deepseek-v3 a1b2c3d4e5f6 38 GB 100% GPU 4 minutes from now
컨텍스트 길이
기본 컨텍스트 윈도우가 생각보다 짧게 설정돼 있다. 긴 문서를 처리할 때는 num_ctx 옵션을 명시적으로 늘려야 한다.
options = {"num_ctx": 8192}
Linux vs Mac 차이
Linux에서는 CUDA를 활용한 GPU 가속이 가능하다. Mac에서는 Metal을 통해 M 시리즈 칩의 GPU를 쓴다. 동일 모델이라도 Linux+RTX 4090 조합이 Mac Mini보다 빠를 수 있다. Mac Mini 클러스터를 여러 대 붙이면 또 다른 이야기가 된다.
마무리
엔드포인트 하나 바꾸는 것으로 API 비용과 데이터 보안 문제를 동시에 해결할 수 있다. 단, 모델을 내려받는 것에서 끝내지 말고 Thinking 모드 분리까지 적용해야 실제 파이프라인에서 쓸 만한 속도가 나온다.
다음 글에서는 Mac Mini 여러 대를 묶어서 추론 요청을 분산하는 방법을 다룰 예정이다.
🐦 X에서 더 빠르게: @baegseungh7061
📚 이 시리즈 더 보기: AI 인사이트
💌 새 글 알림: X 팔로우 또는 블로그 RSS 구독
'AI 인사이트' 카테고리의 다른 글
| Superpowers — 코딩 에이전트가 스스로 설계·계획·TDD를 수행하는 완전 자동 개발 방법론 (0) | 2026.05.07 |
|---|---|
| everything-claude-code — 10개월 에이전트 노하우를 Claude Code에 이식하는 법 (0) | 2026.05.07 |
| ffmpeg + Tailscale로 Mac Mini 클러스터 영상 파이프라인 직접 구축하기 (0) | 2026.05.06 |
| Git Worktree로 브랜치 전환 없이 병렬 개발하는 법 (0) | 2026.05.01 |
| VS Code Remote Development로 서버 성능을 내 손끝에 — SSH 원격 개발 완전 정복 (0) | 2026.04.29 |