
Gemma4 로컬 LLM DGX Spark llama.cpp 최적화 Qwen3.6 비교 LLM OOM 해결
🔍 결론부터: 거대 모델을 다 걷어냈어요
결론부터 말할게요. 2개월 동안 DGX Spark에서 Gemma4 로컬 LLM 운용 조합을 계속 갈아끼운 끝에, 저는 거대 코더 모델(Qwen)을 통째로 내리고 작고 빠른 Gemma4 26B(활성 4B MoE) 하나만 남겼어요. 화려한 80B·35B 코더들을 다 떠나보내고, 14.25GB짜리 양자화 모델 한 개로 정착한 거예요.
처음엔 저도 “큰 게 똑똑하니까 큰 걸 쓰자”는 쪽이었어요. 그런데 실측 데이터가 정반대를 가리켰어요. 작은 Gemma4가 디코드 속도는 3~12배 빠르고, 실무 품질은 거의 다 대등 이상이었거든요. 이 글은 그 2개월의 삽질과 OOM, 그리고 의외의 결론까지를 운용자 시점에서 그대로 풀어낸 개발 로그예요. 모든 수치는 추정이 아니라 제 DGX Spark에서 직접 잰 1차 실측값이에요.
📋 왜 로컬 LLM, 그리고 왜 DGX Spark였나요
저는 코딩 보조와 문서 처리를 로컬에서 돌리고 싶었어요. 어려운 추론은 프론티어 모델(Claude)에게 맡기더라도, 자잘하고 양 많은 작업까지 전부 API로 보내면 비용도 지연도 부담이거든요. 그래서 골랐던 게 NVIDIA DGX Spark예요. 초기 설치 과정이 궁금하다면 DGX Spark 셋업 기록도 참고해 보세요.
DGX Spark는 GB10 Grace Blackwell Superchip에 128GB 통합 메모리(LPDDR5x, 대역폭 273GB/s)를 얹은 데스크톱 AI 머신이에요. 2025년 10월 $3,999로 출시됐는데, 그 뒤 메모리(DRAM) 값이 급등하면서 2026년 2월 $4,699로 올랐어요(NVIDIA 공식 인상). 핵심은 CPU와 GPU가 같은 메모리 풀을 공유한다는 점이에요. 덕분에 70B급 모델도 VRAM 복사 오버헤드 없이 통째로 올릴 수 있어요. 다만 OS 예약분을 빼면 실가용은 대략 121GiB 정도라, 이 “천장”이 나중에 제 발목을 잡게 돼요.
Gemma4 26B-A4B에서 “A4B”는 활성 4B를 뜻해요. 전체 26B 중 토큰마다 4B만 실제로 켜지는 Mixture-of-Experts 구조라, 26B 크기치고 훨씬 빠르게 돌아가요.
🛠️ 2개월의 진화 아크: 모델을 다섯 번 갈아끼웠어요
한 번에 정착한 게 아니에요. 베이스라인부터 현재까지 다섯 단계를 거쳤어요. 각 단계마다 “왜 갈아탔는지”가 있는데, 표로 먼저 보여드릴게요.

| 단계 | 시기 | 주력 코더(Qwen) | 보조(Gemma) | 핵심 실측 | 갈아탄 이유 |
|---|---|---|---|---|---|
| Pre | ~04-04 | Qwen3.5-122B-A10B Q5_K_M | (없음) | 23.7 tok/s, ctx 200K | 최적화 전 베이스라인 |
| S1 | 04-04~04-19 | Qwen3-Coder-Next 80B-A3B MXFP4 (~45GB) | gemma-4-26B-A4B MXFP4 추가 | Qwen 50.98 tok/s | 122B→80B: 속도 +115%, 크기 81→45GB |
| S2 | 04-19~05-19 | Qwen3.6-35B-A3B NVFP4 (~25GB) | (동일) | ctx 1M, SWE-bench Pro 44→49 | 절반 크기 + 옴니모달 + 추론 점수 상승 |
| S3 | 05-19~06-10 | Qwen3.6-27B dense → MTP | (동일) | Qwen 28~40 / Gemma 55~56 | 35B가 1M ctx에서 OOM → 다운사이즈 |
| S4 (현재) | 06-10~ | 폐기 (~99GB 회수) | gemma-4-26B-A4B-it-qat-UD-Q4_K_XL (14.25GB) | 디코드 109.3 tok/s | Gemma가 3~12배 빠르고 실무 대등 이상 |
시작: 122B 단독은 “못 쓰겠다”였어요
처음엔 Qwen3.5-122B를 단독으로 올렸어요. 그런데 23.7 tok/s. 한 글자 한 글자 떨어지는 속도가 답답해서 도저히 실무에 못 쓰겠더라고요. 그래서 더 작고 빠른 Qwen3-Coder-Next 80B로 갈고, 옆에 Gemma4 26B를 보조로 붙여 듀얼 구성으로 갔어요. 두 모델을 각각 8080·8081 포트의 llama.cpp 인스턴스로 띄운 거죠. 이때 Qwen 속도가 23.7 → 50.98 tok/s로 +115% 뛰었어요. 크기도 81GB에서 45GB로 줄었고요.
둘 다 4비트 양자화 포맷이에요. NVFP4는 16개 단위 블록 + 2단 스케일로 MXFP4(32개 블록)보다 더 미세하게 값의 범위를 맞춰 양자화 오차가 더 작아요.
욕심 단계: “더 똑똑한 코더”를 좇았어요
여기서 욕심이 생겼어요. 더 똑똑한 코더가 갖고 싶어서 Qwen3.6-35B-A3B로 올라탔어요. 35B인데 활성은 3B MoE라 가볍고, YaRN으로 컨텍스트를 1M까지 늘릴 수 있고, 옴니모달에 SWE-bench Pro 점수도 44→49로 올랐거든요. 절반 크기에 더 똑똑하니 안 갈아탈 이유가 없었죠. 중간에 vLLM(NVFP4)도 잠깐 끼웠다가 다시 llama.cpp로 돌아왔는데, 그 이유는 제 기록에 안 남아 있어서 여기서는 단정하지 않을게요.
삽질: 1M 컨텍스트를 켰더니 OOM이 났어요
문제는 욕심이 천장을 만났을 때 터졌어요. 35B를 1M 컨텍스트로 띄우니 KV 캐시까지 합쳐 메모리 점유가 ~51GB까지 치솟았고, Gemma까지 함께 올라간 듀얼 구성에서 통합메모리 천장(~124GiB)을 때리면서 OOM이 났어요. 똑똑한 모델을 가장 넓은 컨텍스트로 쓰겠다는 욕심이, 물리 메모리 앞에서 그대로 꺾인 거죠.
그래서 한 단계 내려와 Qwen3.6-27B(dense)로 옮겼어요. 28~40 tok/s 정도로 안정은 됐는데, 이때 옆에서 묵묵히 돌던 Gemma4가 55~56 tok/s를 찍고 있는 게 눈에 들어왔어요. “어라, 보조로 붙여둔 작은 애가 더 빠른데?” 여기서부터 이야기가 뒤집혀요.

📊 정면 비교: 막상 붙여보니 Gemma가 이겼어요
그래서 27B Qwen과 Gemma4를 같은 작업으로 정면 비교했어요. 결과가 의외였어요. 디코드 속도는 비교가 안 됐고, 실무 품질은 거의 다 대등 이상이었어요. Qwen이 이긴 건 딱 하나, 최난도 AIME급 수학뿐이었어요.
| 항목 | Qwen3.6-27B | Gemma4 26B-A4B | 결과 |
|---|---|---|---|
| 디코드 속도 | 28~40 tok/s | 110~130 tok/s | Gemma 압승 (3~12배) |
| 비전 OCR | 6.3초 | 1.4초 | Gemma 압승 |
| 최난도 수학 | 738 ✓ | 657 ✗ | Qwen 유일 우위 |
핵심은 이거예요. Qwen이 유일하게 이긴 영역(최난도 수학)은 어차피 제가 로컬에 안 맡겨요. 그런 건 프론티어 모델(Claude)이 하니까요. 그러니까 로컬에서 굳이 99GB짜리 Qwen을 끌어안고 있을 이유가 사라진 거예요. 보조로 둔 Gemma가 본진이 될 수 있다는 게 데이터로 확인된 순간이었어요.
그래서 결단했어요. Qwen 서비스를 내리고 비활성화해서 약 99GB를 회수했어요.
systemctl stop llama-qwen
systemctl disable llama-qwen
# 통합메모리 ~99GB 회수 → 전부 Gemma에 투자
⚡ 클라이맥스: Gemma 하나를 109 tok/s까지 끌어올렸어요
이제 Gemma 단독이니, 회수한 메모리 여유를 전부 Gemma 최적화에 쏟았어요. 여기서 두 가지 무기를 썼어요. QAT 재양자화와 MTP draft예요.
학습 단계에서 저정밀 연산을 미리 시뮬레이션해 양자화 후 품질 저하를 줄이는 기법이에요. Google이 Gemma4 QAT 체크포인트를 2026년 6월 초에 막 공개했는데, 마침 제 타이밍과 딱 맞았어요.
먼저 기본 MXFP4 양자화에서 Google이 공개한 QAT 체크포인트(gemma-4-26B-A4B-it-qat-UD-Q4_K_XL)로 갈아탔어요. 무게가 16.7GB에서 14.25GB로 줄었는데도 품질 저하는 거의 없었어요. 이 교체만으로 디코드가 57.6 → 80.8 tok/s(+40%)로 뛰었어요.
그다음 MTP draft head를 달았어요.
별도 draft 모델 없이, 모델에 보조 예측 헤드를 달아 한 번의 forward pass로 다음 2~4개 토큰을 동시에 추측하는 speculative decoding 기법이에요. 코드·구조적 출력에서 채택률이 높아요.
llama.cpp에서 MTP draft를 n=2(보수적·안정 설정)로 켰어요. 실행 커맨드는 대략 이런 모양이에요.
llama-server \
-m gemma-4-26B-A4B-it-qat-UD-Q4_K_XL.gguf \
--mmproj mmproj-gemma4-qat.gguf \
--spec-type mtp \
--spec-draft-n-max 2 \
-c 262144 \
--port 8080
제 환경에서 draft 채택률이 약 82%로 나왔고, 디코드는 80.8 → 109.3 tok/s까지 올라갔어요. 출발점(57.6) 대비 +90%예요. 한 단계 한 단계가 다 실측이라, 표로 정리하면 이래요.

| 구성 | 디코드 속도 | 출발점 대비 |
|---|---|---|
| MXFP4 (기본) | 57.6 tok/s | — |
| QAT UD-Q4_K_XL | 80.8 tok/s | +40% |
| QAT + MTP draft n=2 | 109.3 tok/s | +90% |
✅ 교훈: 로컬은 “빠르고 충분히 똑똑한 보조”가 이겨요
2개월의 결론을 한 줄로 줄이면 이래요. 로컬은 거대 만능 모델이 아니라, 빠르고 충분히 똑똑한 보조 모델로 가고, 어려운 건 프론티어에 맡기는 역할 분담이 실전에서 이겨요.
저는 “큰 게 좋다”는 직관을 따라 122B → 80B → 35B → 27B까지 욕심을 냈다가, OOM이라는 물리 한계 앞에서 한 번 꺾이고 나서야 데이터를 똑바로 봤어요. 그랬더니 보조로 둔 작은 Gemma4가 속도 3~12배, 실무 대등 이상이었고, Qwen이 이긴 단 한 영역(최난도 수학)은 애초에 로컬의 몫이 아니었어요. 그래서 99GB를 회수해 Gemma 하나에 몰아주고, QAT와 MTP로 109 tok/s를 만들었어요.
혹시 로컬 LLM 구성을 고민 중이라면, “가장 큰 모델”부터 찾지 말고 “내 작업의 90%를 빠르게 처리할 충분히 똑똑한 모델”부터 찾아보시길 권해요. 나머지 10%는 프론티어에게 맡기면 돼요. 그게 제가 삽질로 배운 가장 비싼 교훈이에요.
📚 References
- NVIDIA DGX Spark 제품 페이지 — nvidia.com (GB10, 128GB 통합 메모리, 273GB/s)
- Google Gemma 4 QAT 발표 — blog.google (2026-06)
- Gemma 4 26B-A4B 모델 카드 — Hugging Face
- Qwen3.6-35B-A3B — qwen.ai (262K→1M 컨텍스트)
- llama.cpp speculative decoding(MTP) 문서 — GitHub
- NVFP4 vs MXFP4 — NVIDIA Technical Blog
- 관련 글: DGX Spark 초기 셋업 기록 — 하드웨어 구성과 llama.cpp 첫 설치 과정을 다뤄요.
다음 글에서는 Gemma4 단독 구성에서 비전 OCR과 도구 호출(tool calling)을 어떻게 붙였는지, 그리고 mmproj 설정에서 겪은 삽질을 이어서 풀어볼게요. 작은 모델 하나로 충분히 즐거운 운용, 같이 해봐요.