slowlp
← 블로그
교훈 2026.06.26 · 6분 읽기

삽질하다 찾은 토큰 절약 두 가지

디폴트 세션 모델을 낮추고 스킬별 model을 고정해 크론 토큰을 줄인 법

교훈

스킬을 하나 돌렸는데 이런 게 떴다.

There's an issue with the selected model (claude-haiku-4-5-20251011).
It may not exist or you may not have access to it.
Run /model to pick a different model.

어제까지 잘 되던 거였다. 그래서 처음엔 정책이 바뀐 줄 알았다. 요 며칠 이 위키의 인덱스랑 다이제스트를 자주 돌리느라 토큰을 많이 썼고, 한도에 걸린 건가 싶었다. 하필 이 에러를 만난 게 토큰을 줄여보겠다고 손을 댄 직후였으니까.

토큰을 줄이려고 시작한 일

매일 도는 크론 작업들이 계속 Opus나 Sonnet을 먹는다. 인덱스, 다이제스트, 백업. 하나하나는 별거 아닌데 세션 모델이 비싼 채로 다 돌면 할당량이 금방 준다.

그러다 공식 문서에서 스킬에 model: 필드를 넣을 수 있다는 걸 봤다. 스킬마다 도는 모델을 고정한다는 얘기다. rsync 한 줄 돌리는 백업을 Opus로 굴릴 이유가 없으니, 스킬별로 모델을 정해두고 디폴트 세션도 Opus에서 Sonnet으로 내리면 꽤 줄겠다 싶었다.

그래서 Claude한테 넘겼다. “기준 정해서 스킬마다 모델 좀 설정해줘.” 알아서 분류해 넣어두겠거니 하고 그날은 잊었다.

그게 위의 에러로 돌아왔다

다음 날 스킬이 안 돌면서 저 메시지가 떴다. 풀어보니 한 번에 두 가지가 꼬여 있었다.

하나는 크레딧이었다. 1M 컨텍스트가 추가 과금이라, 200K를 넘기는 순간 “크레딧 사용으로 전환하라”는 안내가 뜬다. 이게 들쭉날쭉했다. 어떤 땐 뜨고 어떤 땐 안 뜨고. 200K 안쪽이면 조용하다가 긴 컨텍스트로 넘어갈 때만 걸리니까, 제한이 생겼다 없어졌다 하는 것처럼 느껴졌다.

다른 하나가 진짜 범인이었다. 모델 설정이 스킬에 박혀 있다 보니, 기존에 커맨드(commands/)로 있던 걸 스킬(skills/)로 옮겨야 했는데 둘이 모양이 조금 다르다.

여기서 한 가지가 걸렸다. AI한테 물어봐도 이걸 모른다는 거다. 어제오늘 바뀐 거라 학습 시점 이후라서 그렇다. 오히려 “스킬에서 동적으로 모델을 바꾸는 건 안 된다”는 식의 틀린 얘기를 자신 있게 했다. 검색하면 나오는 일반론은 잘 답하면서, 바로 지금 내 환경에서 일어난 일은 제일 약했다. 도구 업데이트를 놓치면 벌어지는 일도 비슷한 구멍이다.

그래서 하나씩 다 넣어봤다

model:에 뭘 넣어야 하는지 예시가 없었다. 풀네임 ID인지 별칭인지, 별칭이면 뭐라고 쓰는지.

풀네임을 넣었더니 위의 그 에러였다. 자세히 보니 내가 넣은 건 claude-haiku-4-5-20251011인데 실제 ID는 claude-haiku-4-5-20251001이었다. 날짜 끝자리가 11이냐 01이냐. 한 글자 차이로 모델을 못 찾는다. 풀네임은 이래서 위험하다.

에러 원인이 오타뿐이냐면, 그것만은 아니다. 나중에 다시 파보니 model: 필드가 실제로 먹히는 경우는 딱 두 가지였다. 스킬을 직접 호출하는 시점에 그 필드가 정의돼 있거나, Workflow·Agent 같은 서브에이전트로 실행하면서 모델을 명시적으로 주입하는 경우. 스킬 안에서 다른 스킬을 부르거나 todo.mdmodel: 태그만 적어두면 적용되지 않는다 — 정의된 시점이 아니라 호출된 시점의 모델을 그대로 물려받기 때문이다. 내가 에러를 만난 순간은 /ingest를 워크플로우로 돌리면서 내부적으로 ingest-chats를 haiku 서브에이전트로 띄우려던 그 시점이었다. 딱 그 주입이 일어나는 순간에야 모델 ID가 실제로 검증됐고, 오타 난 ID라 거기서 막혔다.

별칭으로 바꾸니 됐다. opus, sonnet, haiku 세 개. 이게 확인된 순간 나머지는 빠르게 풀렸다.

기준은 하나로 잡았다

별칭이 풀리고 나니 진짜 질문은 “어느 스킬에 어느 모델을 박을까”였다. 처음엔 작업마다 따져보려다가, 따질수록 헷갈려서 기준을 하나로 좁혔다.

이 스킬이 틀렸을 때, 다시 돌리는 비용이 얼마인가.

blog-seed가 템플릿을 잘못 만들면 한 줄 고치고 다시 돌리면 된다. 싼 모델로 충분하다. blog-draft가 엉망인 초안을 내면 처음부터 다시 써야 한다. 여기서 아끼면 안 된다. 틀려도 고치기 쉬우면 싼 모델, 틀리면 전체를 다시 해야 하면 좋은 모델. 그게 다였다.

이걸로 3계층이 나왔다.

Haiku는 판단 없이 I/O만 하는 것들. ingest-chats(세션 파일 스크립트 실행), blog-seed(템플릿 생성), backup-global-skill(rsync), blog-fix·blog-update(필드 수정).

Sonnet은 추론·분류·가벼운 쓰기. digest(raw→wiki 소화), blog-mine(탐색 후 점수화), blog-publish(메타 검증·링크 생성), lint(정합성 분석).

Opus는 창작·복잡한 설계. blog-draft·blog-rewrite(실제 글쓰기), plan·plan-steps(의존관계 계획), docs-spec(제품 설계).

열 개쯤 분류하다 보면 손이 빨라진다. “이게 Haiku냐 Sonnet이냐”보다 “이게 창작이냐 아니냐”를 먼저 보면 된다. 지금 39개 스킬이 Haiku 9 / Sonnet 20 / Opus 10으로 갈렸다.

실제 설정은 이렇게

스킬 파일 frontmatter에 model: 한 줄이면 끝이다.

---
model: haiku
description: 세션에서 chat 로그를 수집해 마크다운으로 저장
allowed-tools: Bash, Read, Write
---

# /ingest-chats — 채팅 이력 수집
...

넣을 수 있는 값은 haiku, sonnet, opus 세 가지. 풀네임 ID는 버전 날짜가 붙어서 한 글자만 틀려도 위의 그 에러가 난다. 별칭이 안전하다.

이 필드가 있으면 그 스킬이 실행될 때는 디폴트 세션 모델을 무시하고 지정한 모델로 돈다. 나는 디폴트를 Sonnet으로 깔아두고, 스킬마다 Haiku나 Opus로 덮어쓰는 식으로 쓴다.

토큰은 줄었다

전에는 그냥 열려 있는 세션 모델로 다 돌았다. Opus 세션을 열어두면 파일 rsync도 Opus가 하고 템플릿 복사도 Opus가 했다. “Opus로 돌렸는데 잘 됐다”가 사실은 그냥 Opus를 쓴 거였다.

지금은 디폴트가 Sonnet이고 스킬마다 모델이 정해져 있다. ingest-chats, blog-seed 같은 I/O는 Haiku로, 다이제스트나 템플릿 생성처럼 조금 신경 쓸 건 Sonnet으로 고정됐다. 매일 도는 크론의 토큰 비용이 체감상 절반 정도 떨어졌다.

계층을 나누니 따라온 게 하나 더 있다. 어떤 작업이 중요한지가 보인다. Haiku로 해보고 아쉬우면 Sonnet, 그것도 아쉬우면 Opus. 전부 Opus로 돌릴 때는 중요한 작업이나 rsync나 똑같아 보였다.

진짜 교훈은 따로다. 어제 막 바뀐 내 환경은 AI한테 묻지 마라. 별칭 하나씩 넣어보는 게 더 빠르다.

댓글