맥에서 로컬 LLM으로 OpenCode 코딩하기 — 설치부터 실행까지

Ollama 없이 llama.cpp + Qwen 3.6 27B를 로컬에서 돌리고, 오픈소스 코딩 에이전트 OpenCode를 붙여서 "Claude Code처럼" 쓰는 전 과정 정리. 데이터가 밖으로 안 나가고, 토큰 요금도 없다.

opencode 실행 화면.
이 글에서 만드는 것
[OpenCode CLI] --(OpenAI 호환 API)--> [llama.cpp 서버 :8080] --> [Qwen 3.6 27B 모델] 에이전트/툴콜 localhost Apple Silicon GPU
- 클라이언트: OpenCode (오픈소스 터미널 코딩 에이전트)
- 추론 엔진: llama.cpp (Ollama보다 저수준이지만 제어가 확실)
- 모델: Qwen 3.6 27B, 8비트 양자화(Q8_0) — 로컬 코딩의 "스위트 스폿"으로 자주 언급됨
- 모델 저장: 외장 SSD (27GB라 내장 용량 아낌)
테스트 환경
| 항목 | 값 |
|---|---|
| 기기 | Mac Studio (Apple Silicon) |
| 칩 | M3 Ultra (GPU 60코어) |
| 메모리 | 96GB 통합 메모리 |
| 모델 | Qwen3.6-27B Q8_0 (약 27GB) |
| 실측 속도 | 생성 ~21 tok/s, 프롬프트 처리 ~258 tok/s |
💡 통합 메모리가 48GB 이상이면 27B Q8을 여유롭게 돌린다. 32~48GB라면 Q4/Q5 양자화나 더 작은 모델을 권장.
0. 사전 준비
Homebrew와 Node.js(OpenCode 실행용)가 필요하다.
# Homebrew (이미 있으면 건너뜀) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Node.js (없으면) brew install node
1. llama.cpp 설치
brew install llama.cpp
⚠️ 버전이 중요하다. Qwen 3.6 같은 신형 하이브리드 아키텍처(어텐션+SSM)는 최신 빌드에서만 로드된다. 오래된 버전이면 뒤에 나오는
missing tensor에러가 난다. 항상 최신으로:brew upgrade llama.cpp llama-server --version # 버전 번호 확인
2. 모델 다운로드 (외장 SSD로)
Hugging Face CLI로 원하는 양자화 파일 하나만 받는다. 여기서는 외장 SSD myssd에 저장.
# 저장 폴더 만들기 DEST="/Volumes/myssd/llm-models/Qwen3.6-27B" mkdir -p "$DEST" # hf CLI (없으면) pip install -U huggingface_hub # Q8_0 한 파일만 다운로드 (약 27GB) hf download unsloth/Qwen3.6-27B-GGUF Qwen3.6-27B-Q8_0.gguf --local-dir "$DEST"
양자화 고르기
| 양자화 | 크기 | 특징 |
|---|---|---|
| Q8_0 | ~27GB | 사실상 무손실. 메모리 여유 있으면 추천 |
| Q6_K | ~21GB | 품질/용량 균형 |
| Q5_K_M | ~18GB | 무난 |
| Q4_K_M | ~16GB | 가장 작음. 메모리 빠듯할 때 |
8비트는 원본(BF16) 대비 품질 손실이 거의 없으면서 용량을 절반으로 줄인다. 4비트는 더 작고 빠르지만 긴 컨텍스트에서 품질 저하가 있을 수 있다.
3. 서버 실행
llama-server는 OpenAI 호환 API(/v1/chat/completions)를 띄운다. 재사용하기 좋게 스크립트로 만들자.
run-qwen.sh
#!/bin/bash MODEL="/Volumes/myssd/llm-models/Qwen3.6-27B/Qwen3.6-27B-Q8_0.gguf" llama-server -m "$MODEL" \ -ngl 999 \ # 모든 레이어를 GPU에 올림 -fa on \ # flash attention -c 65536 \ # 컨텍스트 64k 토큰 --host 127.0.0.1 --port 8080 \ --jinja # 모델 내장 채팅 템플릿 사용 (툴콜에 필수)
chmod +x run-qwen.sh ./run-qwen.sh
로그에 listening on http://127.0.0.1:8080 이 뜨면 준비 완료.
브라우저로 http://127.0.0.1:8080 을 열면 바로 채팅도 된다.
핵심 옵션
-ngl 999: 전 레이어 GPU 오프로드 (Apple Silicon 통합 메모리에서 필수)-fa on: flash attention으로 메모리/속도 개선-c 65536: 컨텍스트 크기. 코딩 에이전트는 프롬프트가 크므로 넉넉히--jinja: 툴 호출(파일 읽기/쓰기 등)을 쓰려면 반드시 켠다
4. 동작 확인
서버가 살아있는지, 추론이 되는지 확인.
# 헬스체크 curl -s http://127.0.0.1:8080/health # {"status":"ok"} # 추론 테스트 curl -s http://127.0.0.1:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "messages":[{"role":"user","content":"3+4는? 한 줄로 답해줘"}], "max_tokens":1024 }'
⚠️ Qwen 3.6은 "thinking(추론) 모델"이다. 응답이
reasoning_content(사고 과정)와content(최종 답)로 나뉜다.max_tokens를 작게 주면 사고만 하다가 잘려서 답이 비어 보인다. 넉넉히(1024 이상) 주자.
5. OpenCode 설치
brew install opencode opencode --version
6. OpenCode 설정 — 로컬 서버 연결
~/.config/opencode/opencode.json 에 로컬 provider를 등록한다.
{ "$schema": "https://opencode.ai/config.json", "provider": { "llama": { "name": "llama.cpp (local)", "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "http://127.0.0.1:8080/v1", "apiKey": "local" }, "models": { "qwen3.6-27b": { "name": "Qwen3.6-27B Q8 (local)", "tools": true, "reasoning": true, "options": { "temperature": 0.6 } } } } }, "model": "llama/qwen3.6-27b" }
baseURL: llama.cpp 서버 주소 +/v1apiKey: 로컬이라 아무 값이나 ("local")"model": 기본 모델을provider이름/모델id로 지정tools: true: 파일 조작 등 에이전트 기능 활성화
등록 확인:
opencode models | grep qwen3.6 # llama/qwen3.6-27b
7. 실행 & 사용
# 1) 서버가 떠 있어야 함 ./run-qwen.sh # 2) 작업할 프로젝트 폴더에서 cd ~/my-project opencode # 대화형 TUI (Claude Code 느낌) opencode run "README 초안 만들어줘" # 비대화형 단발 실행
기본 모델이 지정돼 있어 옵션 없이 바로 로컬 Qwen을 쓴다.
에이전트가 파일을 직접 쓰는 걸 볼 수 있다:
← Write hello.py Wrote file successfully. Created `hello.py`. ...
8. 트러블슈팅 (실제로 겪은 것들)
① 모델 로딩 실패: missing tensor 'blk.NN.ssm_conv1d.weight'
- 원인: llama.cpp 버전이 낡아서 신형 아키텍처(SSM 하이브리드)를 모름.
- 해결:
brew upgrade llama.cpp후 재실행.
② 답변이 비어서 나옴 (content: "")
- 원인: thinking 모델인데
max_tokens가 작아 사고 도중 잘림.finish_reason: length. - 해결:
max_tokens를 넉넉히(1024+). 또는 아래 thinking off.
③ "안녕" 한 마디인데 답이 너무 느림
- 원인: 에이전트 CLI는 매 요청에 **툴 정의+시스템 프롬프트(약 1만 토큰)**를 붙인다. 첫 요청은 이 큰 프롬프트를 처음부터 처리(cold start)해야 해서 수십 초 걸림. 게다가 thinking까지.
- 해결:
- 같은 세션에서 계속 대화 → llama.cpp가 프롬프트 앞부분을 KV 캐시 재사용, 2번째부터 빨라짐.
- 가벼운 대화는 thinking off (아래).
- 첫 메시지를 "안녕" 대신 실제 작업으로.
④ OpenCode provider 이름 충돌
models목록에 내 모델이 안 보이면, provider 키 이름이 내장 provider와 겹쳤을 수 있다.llamacpp등 고유한 이름으로 바꾼다.
9. 성능 & 사용 팁
- 속도 기대치: 로컬 27B는 신규 파일 생성·단순 리팩터링엔 훌륭하지만, 거대한 기존 코드베이스나 아주 긴 세션은 클라우드 frontier 모델보다 약하다. "관련 파일을 직접 지정하고 명확히 지시"하면 훨씬 잘한다.
- thinking on/off: 잡담·간단 작업용(off)과 어려운 코딩용(on) 모델 항목을 두 개 만들어 상황에 따라 전환하면 편하다.
- 메모리: Q8 27B + 64k 컨텍스트 KV 캐시로 약 40GB대를 쓴다. 브라우저·에디터까지 띄우려면 여유 메모리 확인.
- 완전 오프라인: 서버가 로컬이라 인터넷 없이도 동작한다. 민감 데이터·비행기 안에서도 코딩 가능.
정리
brew install llama.cpp→ 최신으로 업그레이드hf download로 GGUF 모델을 외장 SSD에llama-server ... --jinja로 OpenAI 호환 서버 실행brew install opencode→opencode.json에 로컬 provider 등록opencode로 코딩
토큰 요금 0원, 데이터는 내 맥 안에서만. 로컬 코딩 에이전트, 이제 충분히 실용적이다.



댓글
댓글을 작성하려면 이 필요합니다.