비싼 API보다 무료 지능이 낫다.
지난 몇 주간 MasterCLI—Go, React, PostgreSQL로 만든 AI 네이티브 데스크톱 플랫폼—를 구축하면서 클라우드 API 청구서가 자꾸만 불어났다. 하루 10달러는 대수롭지 않게 들리지만, 알고 보니 쓸데없는 작업에서 나온 돈이었다. 사용자 쿼리 분류, 구조화된 데이터 추출, 메시지 전처리 같은 것들 말이다. GPT-4o-mini 같은 강력한 모델이 필요한 게 아니라, 그냥 제대로 작동하는 뭔가면 되는 작업들이었다.
그때 Google이 Gemma 4 8B를 출시했고, 나는 실제 프로덕션 워크로드에서 로컬로 실행해보기로 결심했다. 결과는 놀라웠을 뿐 아니라, AI 아키텍처를 완전히 다르게 생각하게 만들었다.
게이밍 노트북이 정말 추론 모델을 돌릴 수 있을까?
기대치부터 명확히 하자. 클라우드 GPU 벤치마크 얘기가 아니다. 현실이다:
- 노트북: 표준 RTX 3070 Ti (VRAM 8GB)
- 모델: Gemma 4 8B, Q4_K_M 양자화 (디스크 9.6GB)
- 런타임: Windows 11의 Ollama v0.20.0
모델이 VRAM 용량을 초과한다. 시스템 RAM으로 일부 오프로드된다. 그래도 작동한다.
ollama pull gemma4 한 번이면 9.6GB가 노트북에 앉아서 실행할 준비가 된다. 생성 속도는 모든 작업에서 안정적이었다—초당 19~27 토큰, 워크로드에 따라 달라진다. 프롬프트 처리는 초당 120~850 토큰. 번개같이 빠른 건 아니지만, 클라우드로 왕복하던 분류와 추출 작업에는 충분히 실용적이다.
“모델이 VRAM에 다 들어가지 않으니까 시스템 RAM으로 일부 오프로드된다. 클라우드 GPU 벤치마크가 아니라 현실 상황이다.”
그래서 맞다. 게이밍 노트북으로 이것을 돌릴 수 있다. 진짜 질문은 실제로 쓸모 있을지 여부였다.
Gemma 4가 추론 모델처럼 행동하는 이유?
첫 테스트를 돌렸을 때 가장 충격적인 일이 일어났다. 응답이 비어 있었다. 토큰이 생성되고 있었다—속도 메트릭이 증명했다—인데 JSON의 응답 필드가 비어 있었다.
스트리밍 출력 디버깅에 1시간을 날린 후에야 깨달았다: Gemma 4는 추론 모델이다. DeepSeek-R1이나 OpenAI의 o1처럼, 답하기 전에 연쇄 사고 추론에 토큰을 쓴다.
다만 그 토큰들이 thinking이라는 별도 필드에 있었다.
응답은 이렇게 나왔다:
{"message":{"role":"assistant","content":"","thinking":"여기는 사고 과정..."}}
{"message":{"role":"assistant","content":"","thinking":" ...결론에 도달하기 위해..."}}
// ... 많은 thinking 토큰 ...
{"message":{"role":"assistant","content":"세 가지 주요 패턴은..."}}
모델이 답하기 전에 추론을 하고 있었다. 분류와 추출에는 지능으로 위장한 관료주의다—결과 품질은 좋지만, 레이턴시 비용이 4~7배다.
그다음 킬 스위치를 찾았다: "think": false.
추론 모드를 정말 끄면 어떻게 될까?
추론을 끄면 분류는 7.7배, JSON 추출은 4.5배, 코드 생성은 2배 빨라졌다. 결과 품질은 같다. 훨씬 빠를 뿐이다.
| 작업 | think=true | think=false | 속도 개선 |
|---|---|---|---|
| 분류 | 6.9초 | 0.9초 | 7.7배 |
| JSON 추출 | 19.4초 | 4.3초 | 4.5배 |
| 코드 생성 | 26.7초 | 13.3초 | 2배 |
형식을 미리 알고 제약 조건이 정해진 구조화된 작업에는 추론이 짐짝이다. 자유로운 질문에는 뉘앙스를 잃는다. 레이턴시 비용을 내야 하는 상황에서는 트레이드오프가 명백하다—특히 노트북에서는 레이턴시가 사용자 경험을 죽인다.
1시간을 날린 함정 두 가지
Ollama의 /api/generate 엔드포인트는 Gemma 4에서 작동하지 않는다. response 필드가 비어 나온다. 토큰은 제대로 스트리밍되는데도. /api/chat으로 바꾸면 작동한다. 문서에도 없었다.
두 번째 함정: 도구 호출(함수 호출)에는 num_predict >= 2048이 필요하다. 토큰 예산이 작으면 추론 과정이 할당량 전체를 먹어버려서 모델이 도구를 호출하지 않는다. 충분한 여유가 있으면, 추론을 스킵하고 34 토큰으로 함수 호출을 내보낸다. 1.3초 만에.
나는 이걸 줬다:
{
"name": "search_contracts",
"parameters": {
"query": {"type": "string"},
"min_budget": {"type": "number"},
"category": {"type": "string", "enum": ["IT","construction","services"]}
}
}
프롬프트: “5백만 CNY 이상 IT 계약 찾아”
응답:
{
"name": "search_contracts",
"arguments": {
"category": "IT",
"min_budget": 5000000,
"query": "IT contracts"
}
}
올바른 스키마. 올바른 enum. 올바른 숫자 파싱. 34 토큰, 1.3초, 비용 0원.
갑자기 도구 라우팅이 로컬 모델에서도 실용적으로 느껴졌다.
진짜 작동하는 투 티어 아키텍처
이제 이론이 현실과 만난다. 나는 양 갈래 시스템을 설계했다:
사용자가 요청을 보낸다. 로컬에서 실행 중인 Gemma 4가 판단한다: 이게 간단한 건지 복잡한 건지? 분류, 추출, 의도 감지, 도구 라우팅이면 즉시 반환하자. 진정한 추론이나 자유로운 생성, 복잡한 종합이 필요하면—Claude나 GPT로 넘기자.
사용자 요청
↓
[Gemma 4 로컬 | think=false | ~초당 25 토큰]
↓
├→ 간단함 (분류, 추출, 태그) → 직접 반환
└→ 복잡함 (추론, 생성) → 클라우드로 상향
↓
[Claude/GPT API | 높은 품질, 토큰당 비용]
멋진 부분: 프로덕션 앱의 대부분 “지능” 작업은 사실 멍청한 분류다. 어느 도메인? 어느 네임스페이스? 의도가 뭐? 이건 어떤 종류의 엔티티? 이런 건 AI 가면을 쓴 버킷 문제들이다.
10조 개 토큰으로 훈련된 8B 모델이 게이밍 노트북에서 초당 25 토큰으로 버킷 문제를 0원에 푼다.
프로덕션에 실제로 어떻게 통합했나
MasterCLI의 RAG 나레지 베이스는 7개 네임스페이스에 걸쳐 80개 이상의 도메인을 다룬다. 예전엔 사용자가 검색 위치를 매번 수동으로 지정해야 했다: domains: ["ai-ml"]. 번거로움.
이제:
func (k *DB) ClassifyQuery(ctx context.Context, query string) *QueryClassification {
result, err := k.ollama.QuickClassify(ctx, classifyPrompt, query)
// Returns: {domains: ["ai-ml"], namespaces: ["code"], search_mode: "hybrid"}
}
1초 미만의 도메인 감지. 사용자가 자연스럽게 입력한다. 시스템이 의도를 파악한다.
멀티 에이전트 디스커션 포럼은 더 심각했다. 세 개의 메인 에이전트(Claude, Codex, Gemini)와 코디네이터까지, 모든 메시지를 분석해서 감정, 의도, 컨텍스트, 라우팅 메타데이터를 추출한다. 메시지당 클라우드 API 호출이 4번이다.
나는 메시지 전처리를 로컬 고루틴으로 옮겼다:
```go func (s *Server) handleSpeak(agentID, content string) { go func() { if meta := s.preprocessMessage(ctx,