모델을 로컬에서 실행하는 것은 주말 프로젝트처럼 들릴 수 있습니다. 하지만 실제로는 10분밖에 걸리지 않습니다. 여기 복사-붙여넣기 버전이 있습니다: 도구를 선택하고, 모델을 다운로드한 다음, OpenAI와 호환되는 엔드포인트(endpoint)를 통해 서비스를 제공하고, 아무런 어려움 없이 첫 번째 도구 호출(tool call)을 수행하는 것입니다.
이 글은 모델을 실행하기 위한 시작점으로 간주해야 하며, 파인튜닝 가이드가 아닙니다. 목표는 10분 안에 작동하는 엔드포인트를 만드는 것이며, 더 깊은 성능 조절 장치들(sampler settings, speculative decoding, GPU offload splits)은 별도의 주제이며 또 다른 심층적인 내용입니다.
왜 호스팅된 모델이 그 자리에 있고 실제로 좋은데도 로컬을 사용해야 할까요? 가장 명확한 것은 개인 정보 보호(Privacy) 문제입니다. 아무것도 장치를 벗어나지 않습니다. 다음은 비용(Cost)입니다. 길거나 반복적인 작업은 토큰당 측정(metering)을 멈추게 합니다. 그리고 통제권(Control)이 있습니다. 이는 들리는 것보다 더 중요합니다. 속도 제한(rate limits)이 없고, 갑자기 거부되는 일도 없으며, 버전이 어느 날 아침에 바뀌는 대신 고정됩니다. 당신은 품질과 속도 모두에 대해 비용을 지불하며, 그 가격은 현실적입니다. 마지막 섹션에서는 비용을 지불할 가치가 있는 경우에 대해 다룹니다.
This is fine: quant, context length, KV cache, VRAM math. The ten-minute setup has a few knobs
첫 번째 결정: 어떤 러너(runner)를 사용할 것인가
거의 모든 사람에게 적용할 수 있는 세 가지 도구가 있습니다. 작업 방식에 따라 선택하세요:
| 도구 | 가장 적합한 경우 | 인터페이스 |
|---|
| Ollama | 가장 간단한 CLI, 스크립팅 | ollama run, HTTP API |
| ... | | |
저는 깨끗한 OpenAI와 호환되는 서버를 제공하고 모델 관리에 방해되지 않는 LM Studio의 CLI(lms)를 주요 경로로 사용할 것이며, 그 후에 Ollama 및 llama.cpp에 대한 내용을 보여드리겠습니다. | | |
One mental model: each runner serves an OpenAI-compatible endpoint on localhost that any OpenAI client can call
크기 결정: 아예 들어갈 수 있을까?
무언가를 가져오기 전에 메모리 계산을 먼저 하세요. 양자화된 모델의 파일 크기는 대략 RAM/VRAM 사용량에 컨텍스트(KV 캐시)를 위한 여유 공간이 더해진 정도입니다.
일반적인 가이드라인: 모델 파일 크기 + ~20% ≤ 사용 가능한 RAM/VRAM.
- 8 GB → Q4의 7
8B 모델 (≈45 GB).
- 16 GB → Q4의 13~14B, 또는 8B를 여유롭게 구동 가능.
- 32 GB → Q4의 약 27~34B.
- 64 GB → Q4의 70B가 현실적으로 고려되기 시작합니다.
양자화(Quantization, Q4/Q5/Q8)는 크기를 위해 품질을 희생하는 방식입니다. Q4_K_M이 보통 가장 적절한 균형점(sweet spot)이며, 추가적인 충실도(fidelity)를 원하고 메모리가 충분하다면 Q8만 사용하세요.
Will it fit? Biggest comfortable model at Q4 per RAM tier: 8 GB fits 7-8B, 16 GB fits 13-14B, 32 GB fits 27-34B, 64 GB fits 70B
Buff Doge vs Cheems: 64 GB RAM runs a 70B at Q4, 8 GB RAM barely fits a 7B
LM Studio (lms CLI를 통해)
LM Studio를 설치한 후, CLI가 함께 제공됩니다. 현재 사용 가능한 목록을 확인하고(lms ls), UI나 CLI에서 모델을 가져와 로드하세요:
# 로컬에서 사용 가능한 목록 확인
lms ls
...
LM Studio는 OpenAI 호환 API(기본값 http://localhost:1234/v1)를 제공하며, 이 호환성이 핵심입니다. OpenAI API를 사용하는 모든 것(사용자 스크립트, LiteLLM, 에이전트 프레임워크 등)은 더미 키로 해당 엔드포인트를 가리키기만 하면 변경 없이 작동합니다.
# 서버 확인 및 로드된 모델 보기
curl -s http://localhost:1234/v1/models | jq '.data[].id'
첫 번째 채팅 완료 요청 예시:
curl -s http://localhost:1234/v1/chat/completions \
-H "Authorization: Bearer lm-studio" \
-H "Content-Type: application/json" \
...
Ollama에서도 동일하게 가능합니다
# 모델을 가져와 실행 (첫 실행 시 다운로드)
olllama run llama3.1:8b "다섯 단어로 안녕이라고 말해줘."
...
Ollama는 또한 http://localhost:11434/v1에서 OpenAI와 호환되는 엔드포인트를 노출하므로, 위에서 사용한 것과 동일한 curl 명령어를 포트만 변경하여 사용할 수 있습니다.
llama.cpp에서의 구현 방식
헤드리스 서버(headless servers) 또는 최대의 제어력을 원할 때:
# build once (see the repo for your platform), then serve a GGUF file
llama-server -m ./models/your-model.Q4_K_M.gguf \
-c 16384 --host 0.0.0.0 --port 8080
llama-server는 또한 OpenAI API(/v1/chat/completions)를 지원합니다. 장시간 세션에서 주의할 점은 다음과 같습니다: 컨텍스트가 증가함에 따라 KV cache가 커지고 RSS(Resource State Size)도 시간이 지남에 따라 상승합니다. 만약 지연 시간(latency)이 저하되면, 서버를 재시작하여 초기화해야 합니다.
만약 모델이 무언가를 _수행_하기를 원한다면(함수를 호출하거나, 도구를 구동하는 것), 도구 호출(tool-calling) 기능이 필요하며, 로컬 모델마다 이 부분이 매우 다릅니다. OpenAI의 tools 배열을 보내고 구조화된 tool_calls로 응답하는지 확인해 보세요:
curl -s http://localhost:1234/v1/chat/completions \
-H "Authorization: Bearer lm-studio" -H "Content-Type: application/json" \
-d '{...
만약 깨끗한 tool_calls 배열을 받았다면, 모델이 도구를 구동할 수 있다는 의미입니다. 대신 호출에 대한 서술형 텍스트(prose)를 받는다면, 해당 모델(또는 해당 양자화 버전, quant)은 에이전트 작업(agentic work)에 신뢰성이 떨어지다는 뜻입니다. 다른 것을 선택하거나, 도구 스키마(tool schema)를 작고 간단하게 유지하세요. 이것이 로컬 모델에서 발생하는 가장 큰 함정(gotcha)이며, 별도의 글을 쓸 가치가 있습니다.
Anakin and Padme: my local model does tool calling, so it returns a real tool_calls array, right?
솔직하게 선택하기
로컬 환경이 기본(default) 답변은 아닙니다. 제가 실제로 결정하는 방법은 다음과 같습니다:
- 데이터가 기기를 벗어날 수 없을 때, 작업이 대용량(high-volume)이거나 반복적일 때, 또는 아무도 속도 제한(rate-limits)을 걸지 않는 고정된 모델(pinned model)이 필요할 때는 로컬로 실행하세요.
- 최고 수준의 추론 능력(top-tier reasoning), 긴 단계의 체인 전반에 걸친 신뢰성(reliability)이 필요하거나, 단순히 메모리 및 양자화(quantization)를 직접 관리하고 싶지 않을 때는 호스팅 환경을 유지하세요.
- 대부분의 실제 설정은 그 중간 지점에 위치합니다: 대량 작업(bulk)은 로컬에서 처리하고, 정말 어려운 몇몇 단계는 호스팅 모델을 사용합니다.
Drake: no to a per-token bill and rate limits for a repetitive job, yes to local for the bulk and hosted for the hard parts
핵심 요약 (Takeaway)
러너(runner)를 선택하고, 메모리 계산을 하고, 모델을 로드하고, 엔드포인트(endpoint)에 도달하는 과정은 정말 10분밖에 걸리지 않습니다. 중요한 결정은 그 이후에 옵니다: 얼마나 깊이 양자화할지, 그리고 모델이 tool-calling을 지원할 수 있는지 여부입니다. 왜냐하면 그것이 위에 구축하는 모든 에이전틱(agentic)한 기능을 성공시키거나 실패하게 만드는 요소이기 때문입니다.
다음 내용: 로컬 모델이 tool-calling에서 실패하는 이유와 이를 우회하여 설계하는 방법.