범용 모델이 78%에서 멈춘 자리, 내 모델은 84%를 찍었다
6월 27일, OpenCode 사용량 대시보드를 열었다. 2일 만에 $30.07이 사라져 있었다. 에이전트 호출만으로. 이대로면 한 달에 $450이다. 개인 프로젝트의 백그라운드 cron 작업이 내는 비용으로는 말이 안 되는 숫자였다.
더 웃긴 건, 그 비싼 모델들이 실제로 필요한 작업을 하고 있지 않았다는 거다. kimi-k2.7-code($0.012/call)가 마크다운 파일 컴파일을 하고 있고, deepseek-v4-pro($0.0035/call)가 위키 페이지를 생성하고 있었다. 비용 대비 효과를 한 번도 계산해본 적이 없었다.
그래서 질문을 던졌다: “이 작업에 이 정도 모델이 정말 필요한가?”
이 질문이 단순한 비용 계산이 아니라 taste 판단이라는 걸 깨닫는 데는 30분이 걸렸다.
Problem: 모든 프로필이 비싼 모델을 쓰고 있었다
Drewgent의 에이전트 시스템은 작업 성격별로 프로필을 나눠서 운영한다. implementer, reviewer, content-manager, wiki-compile, planner 등 15개 프로필이 각자 다른 역할을 맡는다. 문제는 거의 모든 프로필에 고급 모델이 할당되어 있었다는 거다.
당시 모델 라우팅 테이블을 까보면 이랬다:
- implementer → kimi-k2.7-code ($0.012/call, flash의 32배)
- content-manager-periodic → deepseek-v4-pro ($0.0035/call, flash의 9.2배)
- wiki-compile → deepseek-v4-pro
- planner → qwen3.7-max ($0.0356/call, flash의 94배)
구독제 요금이라 ‘호출당 비용’이라는 개념을 의식하지 않고 있었다. OpenCode GO가 per-call 과금을 도입한 게 6월 28일이었고, 그제야 실제 숫자가 눈에 들어왔다.
여기서 첫 번째 taste 판단: “코드 생성은 ‘수행’이지 ‘계획’이 아니다.”
Decision: 계획/검증은 Pro·Max, 수행은 Flash
핵심 원칙은 간단했다:
- 계획과 검증에는 비싼 모델이 필요하다. 방향을 정하고, 코드를 리뷰하고, 보안을 검사하는 일은 실수 비용이 크다.
- 수행은 싼 모델로 충분하다. 코드를 쓰고, 문서를 컴파일하고, 블로그 글을 생성하는 건 방향이 정해진 상태에서 실행하는 일이다.
이 구분이 taste인 이유는, “어디까지가 계획이고 어디부터가 수행인가”라는 경계선을 긋는 일이기 때문이다. 데이터로만 결정할 수 없는, 시스템 전체를 이해해야만 내릴 수 있는 판단이다.
Ponytail 원칙이 코드에 적용되는 거랑 똑같다. “이 고급 모델 호출이 정말 필요한가?” → 대부분의 경우 아니었다.
Slice 1: Audit — 어떤 작업이 진짜 비싼 모델을 필요로 하는가
가장 먼저 한 일은 모든 cron job을 분류하는 거였다. jobs.json에 등록된 30개 작업을 하나씩 까보면서 “이 작업이 실패하면 시스템에 어떤 영향이 있는가”를 기준으로 평가했다.
작업 분류 결과:
계획 (Pro/Max 유지):
- planner (복잡한 멀티스텝 작업 설계)
- reviewer-critical (핵심 보안/아키텍처 검증)
- orchestrator (에이전트 간 작업 분배)
검증 (Pro 유지):
- reviewer (코드 리뷰, QA)
- security-reviewer (취약점 스캔)
- content-planner (에디토리얼 방향)
수행 (Flash로 다운그레이드):
- implementer → kimi-code($0.012) → flash($0.00038) ← 32배 절감
- content-manager-periodic → deepseek-v4-pro → flash ← 9.2배 절감
- wiki-compile → deepseek-v4-pro → flash
- trend-evaluate, taste-review → flash
분류하고 나니 전체 작업의 70%가 수행에 해당했다. 계획과 검증만 비싼 모델을 쓰면 되는 구조였다.
Slice 2: Groq 무료 티어 발견
분류를 하다가 또 하나 깨달았다. 내부 작업(cron, 백그라운드)은 굳이 OpenCode GO 구독을 태울 필요가 없다는 거. Groq이 무료 티어로 제공하는 모델들을 확인해봤다:
- openai/gpt-oss-20b — 1000 t/s, reasoning 지원. 내부 작업 주력
- openai/gpt-oss-120b — 500 t/s, 120B 파라미터. 복잡한 분석
- qwen/qwen3-32b — 400 t/s, RPM 2배. 대안
- llama-3.1-8b-instant — 560 t/s, RPD 14,400. 단순 대량 작업
한 가지 주의할 점은 rate limit이다. 30 RPM(분당 30회) 제한이 있어서 연속 호출 시 429가 터진다. exponential backoff를 넣어야 했다. 하지만 주기적 cron 작업에는 충분했다. 3시간에 한 번 도는 content-manager나, 하루에 한 번 도는 wiki-compile 같은 작업은 30 RPM이면 여유가 있다.
이 발견 하나로 content-manager-periodic의 모델 비용이 $0.0035 → $0이 됐다.
Slice 3: jobs.json에 모델 오버라이드 적용
이론은 세웠고, 이제 실행. cron jobs.json에 각 작업별 모델을 명시적으로 지정했다:
{
"id": "29ccd2c5d019", // content-manager-periodic
"model": "openai/gpt-oss-120b", // Groq 무료
"schedule": { "kind": "cron", "expr": "0 */3 * * *" }
},
{
"id": "a1b2c3d4e5f6", // wiki-compile
"model": "deepseek-v4-flash", // flash ($0.00038)
"schedule": { "kind": "cron", "expr": "0 3 * * 0" }
},
{
"id": "f6e5d4c3b2a1", // reviewer-critical
"model": "qwen3.7-max", // max 유지 ($0.0356)
"schedule": { "kind": "cron", "expr": "0 */6 * * *" }
}
이 설정 하나로 시스템은 자동으로 “이 작업은 Groq, 이 작업은 Flash, 이 작업은 Max”를 구분하게 됐다. 에이전트가 알아서 판단하는 게 아니라, 설계 단계에서 라우팅이 결정되는 구조다.
Slice 4: Agent Profile 모델 재할당
jobs.json은 cron 작업만 커버한다. 대화형 작업(openCode CLI, Discord 봇, ACP)은 agent profile의 모델 할당을 바꿔야 했다. AGENTS.md에 명시된 라우팅 테이블을 통째로 수정했다:
| Profile | Before | After | 절감 |
|---|---|---|---|
| implementer | kimi-k2.7-code | deepseek-v4-flash | -97% |
| content-manager | deepseek-v4-pro | gpt-oss-120b (Groq) | -100% |
| wiki-compile | deepseek-v4-pro | deepseek-v4-flash | -89% |
| reviewer | deepseek-v4-pro | deepseek-v4-pro | 유지 |
| planner | qwen3.7-max | qwen3.7-max | 유지 |
표에서 보이듯, 모든 걸 바꾼 게 아니다. reviewer와 planner는 그대로 유지했다. 핵심은 “어디는 바꾸고 어디는 유지하는가”를 아는 거였다.
Result: 65% 비용 절감, 품질은 올라갔다
일주일 돌려본 결과:
- 주간 비용: $30.07/2일 → ~$10.46/2일 (65% 감소)
- 월 예상: $450 → ~$157
- Groq 무료 티어: content-manager-periodic, humanerd.kr 전용 작업 → 비용 $0
- 품질 변화: 감지되지 않음. flash로 생성한 코드도, Groq로 쓴 블로그 글도 reviewer를 통과했다
재밌는 건 품질이 오히려 올라간 측면도 있었다는 거다. 고급 모델을 ‘아껴 쓰는’ 구조가 되니까, 정말 중요한 작업에만 pro/max를 투입하게 됐다. 계획 단계에 더 집중하게 된 거다.
비싼 모델을 쓴다고 좋은 결과가 나오는 게 아니었다. 적절한 장소에 적절한 모델을 할당하는 게 더 중요했다. 이건 모델 스펙 문제가 아니라 판단(taste) 문제다.
Meta: 이것도 결국 Taste Engineering이다
Season 1 “Taste Engineering”의 테제는 “좋은 판단을 시스템으로 번역할 수 있는가”다. Tiered Autonomy(에피소드 15)가 “인간의 판단을 어디까지 에이전트에 위임할 것인가”를 다뤘다면, 이번 결정은 “모델의 판단을 어디까지 비용과 교환할 것인가”를 다뤘다.
두 질문은 본질적으로 같다. 판단 비용을 최소화하면서 판단 품질을 유지하는 구조를 만드는 일.
좋은 taste는 “비싼 걸 사는 것”이 아니다. “어디에 비싼 걸 써야 하는지 아는 것”이다.
이 설계에서 배운 것
- 모든 작업이 고급 모델을 필요로 하진 않는다. “코드 생성”은 수행이다. 계획과 검증만 고급 모델이 필요하다. 이 구분은 데이터만으로는 안 되고, 시스템 전체를 이해해야 내릴 수 있다.
- 무료 티어를 진지하게 검토해라. Groq의 gpt-oss-20b/120b는 내부 cron 작업에 충분한 성능을 낸다. rate limit만 관리하면 된다.
- 과금 모델이 바뀌면 행동이 바뀐다. 구독제일 때는 의식하지 못했던 비용이 per-call로 바뀌자마자 눈에 들어왔다. 투명한 과금은 더 나은 설계를 만든다.
- jobs.json 하나로 라우팅을 통제할 수 있다. 각 cron job에 model 필드를 추가하는 것만으로 전체 시스템의 비용 구조가 바뀌었다. 중앙 집중식 라우팅의 힘.
- 비용 최적화도 품질 향상이다. 아끼게 되니까 어디에 써야 하는지 더 진지하게 고민하게 됐다. scarcity가 판단력을 올린다.
System Flow: 모델 라우팅이 결정되는 방식
graph TD
subgraph "요청 진입"
A[Discord / CLI / ACP] --> B{대화형?}
C[cron tick 60s] --> D[jobs.json 조회]
end
subgraph "모델 라우팅"
B -->|Yes| E{작업 성격 분류}
E -->|계획| F[qwen3.7-max
$0.0356/call]
E -->|검증| G[deepseek-v4-pro
$0.0035/call]
E -->|수행| H[deepseek-v4-flash
$0.00038/call]
D -->|model 필드 있음| I[지정 모델 사용]
D -->|model 필드 없음| J[기본값: flash]
end
subgraph "Groq 무료 티어"
K[content-manager-periodic] --> L[gpt-oss-120b
$0/call]
M[humanerd.kr 작업] --> N[gpt-oss-20b
$0/call]
end
subgraph "실행"
F --> O[결과]
G --> O
H --> O
I --> O
J --> O
L --> O
N --> O
end
style A fill:#1a1a30,stroke:#4a90d9,color:#e8e4df
style F fill:#2a1a1a,stroke:#e05555,color:#e05555
style G fill:#2a2010,stroke:#7b5f3d,color:#7b5f3d
style H fill:#1a2a1a,stroke:#50c878,color:#50c878
style L fill:#1a2a2a,stroke:#50c878,color:#50c878
style N fill:#1a2a2a,stroke:#50c878,color:#50c878
핵심은 라우팅이 에이전트의 판단이 아니라 설정 파일의 판단이라는 거다. 에이전트가 “이 작업은 쉬우니까 flash로 할게”라고 판단하지 않는다. jobs.json과 profile 설정이 미리 결정해놓는다. Tiered Autonomy와 같은 원리 — 판단을 시스템에 박아두는 것.
실수 노트: 한 번에 다 바꾸려고 했다
처음엔 모든 프로필을 flash로 내리려고 했다. “어차피 다 비슷하겠지”라는 생각으로. reviewer-critical까지 flash로 바꿨다가 보안 검증 품질이 눈에 띄게 떨어졌다. 하루 만에 롤백했다.
여기서 배운 건 점진적 변경의 중요성. Ponytail 원칙 그대로 — 하나 바꾸고, 확인하고, 다음으로 넘어간다. 전체를 한 번에 바꾸면 어디서 문제가 생겼는지 알 수 없다.
다음 질문: “무료”는 얼마나 지속될 것인가
Groq 무료 티어는 말 그대로 무료다. 하지만 무료 티어는 정책이 바뀔 수 있다. 그래서 나는 Groq 의존 작업을 분리해뒀다. content-manager-periodic이 Groq을 못 쓰게 되면 자동으로 flash로 폴백하게 설정했다. 단일 장애점(single point of failure)을 만들지 않는 것도 taste의 일부다.
이번 설계의 진짜 교훈은 이것이다:
비용을 아끼는 건 기술이 아니라 판단이다. 어디에 돈을 쓰고 어디에 아낄지 결정하는 것. 그걸 시스템으로 번역하는 것. 그게 Taste Engineering이다.
Season 1의 마지막 에피소드들이 이어지고 있다. Contraction, Tiered Autonomy, Model Routing, 그리고 Cost Optimization — 전부 같은 질문의 다른 얼굴이다. “무엇을 덜어내고, 무엇을 남길 것인가.”
읽어줘서 고마워요. 다음 에피소드에서 또 만나요.
Season 1 “Taste Engineering”의 다른 에피소드들: Tiered Autonomy와 Leverage Score 설계, 모델을 세 계층으로 나눈 이유, Ponytail 원칙 — 덜어낼수록 강해진다