🔄 [2025.04.10 업데이트] 이 글의 모델 추천에 오류가 있었습니다
이 글에서 추천한 Qwen2.5-Coder-14B는 현재 사용 중인 Qwen3-Coder-30B-A3B (Ollama Q4) 대비 코딩 품질이 낮습니다. Qwen3 기술보고서 기준으로 Qwen3-Coder는 Intelligence Index 20점 vs Qwen2.5-14B 수준이며, 세대 차이가 성능 격차를 만듭니다.
오류가 발생한 배경: vLLM에서 Qwen3-Coder-30B-A3B를 올렸을 때 --enforce-eager + PP=3 조합으로 속도가 너무 느려져서 "돌아가는 대안"으로 Qwen2.5-Coder-14B를 선택했는데, 이것이 실제로는 모델 품질 후퇴였습니다.
정정된 권장 구성:
단일~소수 사용자 → Ollama + Qwen3-Coder-30B-A3B 유지가 현재 최선
5명 이상 동시 사용 → vLLM + Qwen3-14B Dense FP16 (Qwen2.5-14B 아님)
자세한 비교 분석: Ollama vs vLLM 동시 사용자 비교 글 참고

🎯 이 글의 핵심 요약
- Claude Code의 Opus/Sonnet/Haiku는 사실상 단일 모델에서 동작한다 — 자동 라우팅 없음
- 최적 구성: Qwen2.5-Coder-14B (GPU 0,1 PP=2) + 1.5B (GPU 2 단독)
- max-model-len 2048은 즉시 16384로 올려야 — 현재 설정은 파일 편집 불가 수준
CLAUDE_CODE_ATTRIBUTION_HEADER=0설정 누락 시 KV 캐시 무력화로 속도 90% 저하- Continue.dev는 chat(8000)과 자동완성(8001)을 포트별로 분리 연결 — 프록시 불필요
🚀 시작하며 — 삽질의 역사
Tesla V100 32GB × 3장, 총 96GB VRAM. 이걸로 vLLM을 올려서 Claude Code를 연결하는 게 목표였는데, 솔직히 말하면 꽤 긴 여정이었습니다. Qwen3-Coder-30B Dense는 너무 느리고, AWQ는 V100 SM7.0에서 커널 자체가 없어서 아예 실패. 결국 Qwen2.5-Coder-15B(사실상 14B), pipeline-parallel-size 3, max-model-len 2048로 어찌어찌 돌아가는 상태까지 왔습니다.
그런데 여기서 멈추기엔 아쉬웠어요. Claude Code에서 ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL을 어떻게 설정해야 하는지, 모델을 어떻게 분리해야 하는지 제대로 분석이 필요했습니다. 이 글은 그 분석 결과를 정리한 실전 레퍼런스입니다.

🔍 Claude Code의 Opus/Sonnet/Haiku — 실제로 어떻게 동작하나?
가장 중요한 사실부터. Claude Code 바이너리 분석(GitHub issue #27665) 결과, 내부 모델 라우팅은 사실상 없다고 봐도 됩니다.
// 실제 라우팅 함수 (단순화)
function getRuntimeMainLoopModel({ permissionMode, mainLoopModel }) {
// opusplan 모드의 계획 단계에서만 Opus 호출
if (getUserSpecifiedModel() === "opusplan" && permissionMode === "plan")
return getDefaultOpusModel();
// 나머지 모든 작업: 세션에 설정된 단일 모델
return mainLoopModel;
}
각 티어의 실제 역할을 정리하면 이렇습니다.
opusplan 모드의 계획 단계에서만 호출됨.
opusplan 실행 단계 + 일반 코딩 작업 전반.
코딩 작업에는 전혀 관여 안 함.
⚠️ 결론: 로컬 vLLM 환경에서 세 티어에 각각 다른 모델을 매핑하는 건 이론상 가능하지만 실질적 효과가 거의 없습니다. Claude Code가 Haiku를 호출하는 빈도는 극히 낮고, opusplan 모드를 쓰지 않으면 Opus/Sonnet 구분도 무의미합니다. 단일 14B 모델 매핑이 가장 현실적입니다.

📊 V100 3장 VRAM 분석 — PP=3 vs PP=2+1 분리
현재 구성의 VRAM 사용량 (PP=3)
Qwen2.5-Coder-14B FP16을 GPU 3장에 PP=3으로 올릴 때 실제 VRAM 분포입니다.
| 구성 요소 | GPU 0 | GPU 1 | GPU 2 |
|---|---|---|---|
| 모델 가중치 | ~10.3 GB | ~8.8 GB | ~10.3 GB |
| CUDA/활성화 오버헤드 | ~2.0 GB | ~2.0 GB | ~2.0 GB |
| KV 캐시 (max-len 2048) | 0.13 GB | 0.13 GB | 0.13 GB |
| 미사용 VRAM | ~17 GB | ~19 GB | ~17 GB |
😱 충격적인 사실: KV 캐시에 GPU당 128MB만 사용되고 있습니다. gpu-memory-utilization 0.95로 GPU당 ~18GB를 KV 캐시용으로 확보했는데, 실제 사용량은 그 0.7%에 불과합니다. max-model-len 2048은 심각하게 보수적인 설정입니다.
추천 구성: PP=2 + GPU 2 분리 (2+1 전략)
PP=3 대신 GPU 0,1을 PP=2로 14B 메인 모델에 배치하고, GPU 2는 1.5B 자동완성 전용으로 분리합니다. PP=2는 인터-GPU 통신이 1홉 줄어서 레이턴시가 오히려 개선될 수 있어요.
| GPU | 모델 | 역할 | 포트 | max-model-len |
|---|---|---|---|---|
| GPU 0, 1 | Qwen2.5-Coder-14B FP16 | 메인 코딩 (Opus/Sonnet) | :8000 |
16384 |
| GPU 2 | Qwen2.5-Coder-1.5B FP16 | 자동완성 (Haiku) | :8001 |
32768 |
💡 왜 PP를 선택하나? NVLink가 없는 PCIe 환경에서 TP(Tensor Parallel)는 all-reduce 통신으로 심각한 병목이 됩니다. PP(Pipeline Parallel)는 스테이지 간 활성화 텐서만 전송하므로 (~40MB/요청) PCIe 15GB/s에서 전송 시간이 ~2.7ms에 불과합니다.
🏆 Opus/Sonnet/Haiku 최적 모델 매핑
Opus + Sonnet: Qwen2.5-Coder-14B-Instruct (FP16)
Claude Code가 두 티어를 실질적으로 구분하지 않으므로 동일 모델로 매핑합니다. Qwen2.5-Coder-14B는 HumanEval 90+%로 동급 최강 코드 모델이며, 128K 컨텍스트를 지원합니다.
| 모델 | HumanEval | Context | V100 FP16 | 비고 |
|---|---|---|---|---|
| Qwen2.5-Coder-14B ✅ | 90+% | 128K | 완전 지원 | 최선택 |
| Qwen2.5-Coder-7B | 88.4% | 128K | 완전 지원 | 차선 |
| DeepSeek-Coder-6.7B | 73.8% | 16K | 완전 지원 | 컨텍스트 짧음 |
| Qwen2.5-Coder-32B | 92%+ | 128K | ⚠️ 매우 느림 | 3장 독점 |
| CodeLlama-13B | ~65% | 100K | 완전 지원 | 품질 열등 |
Haiku: Qwen2.5-Coder-1.5B-Instruct (FP16)
자동완성 전용으로 GPU 2에 단독 배치합니다. 가중치 ~3GB로 VRAM 여유가 넘쳐서 max-model-len 32768까지도 문제없습니다.
- Qwen2.5-Coder-1.5B: HumanEval 70.7%, 컨텍스트 32K — 자동완성 FIM 최적
- Continue.dev 자동완성용은 Base 모델이 Instruct보다 FIM 품질이 높음
- Claude Code 백그라운드(제목 생성 등)용은 Instruct 모델 권장
- DeepSeek-Coder-1.3B는 16K 컨텍스트로 열등, 선택 불필요
⚠️ max-model-len 2048 — 파일 편집이 왜 안 되는지
실제 코드 편집에서 얼마나 많은 토큰이 필요한지 분석해보면 2048이 얼마나 부족한지 바로 나옵니다.
| 작업 유형 | 필요 토큰 | 2048으로 가능? |
|---|---|---|
| Claude Code 시스템 프롬프트 | ~1,500 tok | ⚠️ 이미 75% 소진 |
| 단일 파일 편집 (짧은 함수) | 1,500~3,000 tok | ❌ 불가능 |
| 멀티파일 리팩토링 | 3,000~11,000 tok | ❌ 완전 불가 |
| 코드 리뷰 (diff 포함) | 4,000~8,000 tok | ❌ 불가능 |
| 권장 설정 (16384) | ✅ 멀티파일 리팩토링 대부분 처리 가능 | |
📐 VRAM 계산: PP=2 구성에서 GPU당 KV 캐시 잔여 ~14GB. max-model-len 16384 설정 시 GPU당 KV 캐시 소모량은 약 1.5GB에 불과합니다. 2048 → 16384로 바꿔도 VRAM은 전혀 문제없습니다.
⚙️ 최종 설정 — 실전 명령어 모음
① vLLM 멀티 인스턴스 시작 스크립트
#!/bin/bash
# ═══════════════════════════════════════════════════
# Instance 1: Qwen2.5-Coder-14B — 메인 코딩 모델
# GPU 0,1 사용 / Pipeline Parallel 2 / Port 8000
# ═══════════════════════════════════════════════════
CUDA_VISIBLE_DEVICES=0,1 \
VLLM_ATTENTION_BACKEND=XFORMERS \
VLLM_USE_V1=0 \
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True \
NCCL_P2P_DISABLE=1 \
vllm serve /models/Qwen2.5-Coder-14B-Instruct \
--port 8000 \
--host 0.0.0.0 \
--dtype float16 \
--pipeline-parallel-size 2 \
--max-model-len 16384 \
--gpu-memory-utilization 0.92 \
--enforce-eager \
--enable-chunked-prefill=False \
--served-model-name qwen-coder-14b \
--api-key "local-key-123" \
--trust-remote-code &
# ═══════════════════════════════════════════════════
# Instance 2: Qwen2.5-Coder-1.5B — 자동완성 전용
# GPU 2 단독 / Port 8001
# ═══════════════════════════════════════════════════
CUDA_VISIBLE_DEVICES=2 \
VLLM_ATTENTION_BACKEND=XFORMERS \
VLLM_USE_V1=0 \
vllm serve /models/Qwen2.5-Coder-1.5B-Instruct \
--port 8001 \
--host 0.0.0.0 \
--dtype float16 \
--max-model-len 32768 \
--gpu-memory-utilization 0.90 \
--enforce-eager \
--enable-chunked-prefill=False \
--served-model-name qwen-coder-1.5b \
--api-key "local-key-123" \
--trust-remote-code &
echo "✅ vLLM 인스턴스 시작: 14B @ :8000 (GPU 0,1) | 1.5B @ :8001 (GPU 2)"
wait
💡 V100 필수 플래그 설명--dtype float16 — BF16 미지원 필수 설정--enforce-eager — V100 CUDA 그래프 문제 방지--enable-chunked-prefill=False — V100 FP16 chunked prefill 버그 우회 (vLLM issue #11352)VLLM_USE_V1=0 — vLLM V1 엔진의 V100 비호환 회피NCCL_P2P_DISABLE=1 — PCIe 환경 NCCL P2P 통신 오류 방지
② Claude Code 설정 (~/.claude/settings.json)
{
"env": {
"ANTHROPIC_BASE_URL": "http://localhost:8000",
"ANTHROPIC_AUTH_TOKEN": "local-key-123",
"ANTHROPIC_MODEL": "qwen-coder-14b",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "qwen-coder-14b",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "qwen-coder-14b",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "qwen-coder-14b",
"CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
"DISABLE_PROMPT_CACHING": "1",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"API_TIMEOUT_MS": "300000"
}
}
🚨 가장 중요한 설정: CLAUDE_CODE_ATTRIBUTION_HEADER: "0"
이 값이 없으면 Claude Code가 매 요청마다 시스템 프롬프트에 고유 해시를 삽입해서 vLLM의 KV 캐시가 완전히 무효화됩니다. 추론 속도 90% 저하의 원인이 될 수 있어요. 반드시 settings.json의 env 섹션에만 넣어야 합니다 — export로는 동작하지 않습니다.
③ Continue.dev config.json (~/.continue/config.json)
{
"models": [
{
"title": "Qwen2.5-Coder-14B (Main)",
"provider": "openai",
"model": "qwen-coder-14b",
"apiBase": "http://localhost:8000/v1",
"apiKey": "local-key-123",
"contextLength": 16384,
"completionOptions": {
"maxTokens": 4096,
"temperature": 0.1
}
}
],
"tabAutocompleteModel": {
"title": "Qwen2.5-Coder-1.5B (Autocomplete)",
"provider": "openai",
"model": "qwen-coder-1.5b",
"apiBase": "http://localhost:8001/v1",
"apiKey": "local-key-123",
"contextLength": 4096,
"completionOptions": {
"maxTokens": 256,
"temperature": 0.0,
"stop": ["\n\n", "\r\n\r\n"]
}
},
"tabAutocompleteOptions": {
"debounceDelay": 300,
"maxPromptTokens": 2048,
"multilineCompletions": "always"
}
}
✅ Continue.dev의 장점: tabAutocompleteModel로 chat과 자동완성을 각각 다른 포트에 직접 연결할 수 있습니다. LiteLLM 같은 프록시 없이도 GPU 2의 1.5B 모델이 자동완성 전용으로 동작합니다.

✅ 즉시 해야 할 3가지
VRAM 여유가 충분합니다. 이것 하나만 해도 파일 편집 품질이 극적으로 달라집니다.
14B 품질은 그대로, 자동완성은 별도 경량 모델이 담당해서 응답 속도 향상.
CLAUDE_CODE_ATTRIBUTION_HEADER: "0" 추가
KV 캐시 무효화 방지. 이 설정이 없으면 모든 요청이 콜드 스타트 수준으로 느려집니다.
💬 마치며
V100 3장 폐쇄망 환경이라는 제약이 꽤 컸는데, 결국 AWQ 실패, 30B 속도 문제를 겪고 나서야 "14B PP=2 + 1.5B 단독"이 이 환경에서의 최적해라는 걸 확인했습니다. Claude Code의 Opus/Sonnet/Haiku 라우팅이 생각보다 단순하다는 것도 의외였어요. 처음엔 복잡하게 LiteLLM 프록시까지 구성하려 했는데, 분석해보니 불필요했습니다.
max-model-len 2048에서 파일 편집이 안 되는 분들, 꼭 16384 이상으로 올려보세요. VRAM은 충분하고, 이것 하나가 Claude Code 사용 경험을 완전히 바꿔줍니다.
설정하다가 막히는 부분이나 다른 경험 있으시면 댓글 남겨주세요. 같은 환경에서 고생하시는 분들과 정보 나누고 싶습니다 🙏
- vLLM 공식 Claude Code 연동 가이드:
docs.vllm.ai/en/latest/serving/integrations/claude_code/ - vLLM V100 chunked-prefill 버그: GitHub issue #11352
- Claude Code 모델 라우팅 분석: GitHub claude-code issue #27665
- Continue.dev 공식 문서:
docs.continue.dev
※ 이 글은 실제 Tesla V100 3장 폐쇄망 환경에서의 테스트와 오픈소스 커뮤니티 분석을 기반으로 작성되었습니다. 환경에 따라 설정값이 달라질 수 있으므로 VRAM 여유를 확인하며 적용하시기 바랍니다.
'Tech > AI & LLM' 카테고리의 다른 글
| Google AI Edge Gallery 완전 정복 — LiteRT-LM·Gemma 4·Agent Skills 기술 심층 분석 (2026) (1) | 2026.04.10 |
|---|---|
| Ollama vs vLLM 완전 비교 — V100 3장 환경에서 동시 사용자 20명 서빙하기 (1) | 2026.04.10 |
| OpenWebUI RAG 설정 최적화 완벽 가이드 — bge-m3 vs nomic-embed-text vs qwen3-embedding 비교 (1) | 2026.04.10 |
| 맥미니 M5 출시일·가격·스펙 총정리 — M4 대비 정밀 비교분석 (2026) (0) | 2026.04.08 |
| 노트북LM으로 영어 공부하는 법 총정리 — 무료 AI 영어 듣기 학습 완벽 가이드 (0) | 2026.04.07 |