에이전트를 2주 돌리고 나서 청구서를 열었더니, 도클링 재생성과 import 정렬 같은 작업들이 프론티어 모델 예산의 대부분을 잡아먹고 있었다. 반면 큐 컨슈머의 타이밍 버그—진짜 어려운 문제—는 도클링 작업과 똑같은 모델에, 똑같은 shallow retry로 처리됐고, 결국 4일 뒤 롤백됐다. dev.to에 공유된 이 사례는 AI 코딩 에이전트가 비용 문제를 일으키는 방식이 '모델이 비싸서'가 아니라는 걸 정확하게 짚는다. 감시 없이 방치된 에이전트는 모든 호출에서 동일한 지출 결정을 내린다—그리고 기본값은 항상 최고가 모델이다.
모델 라우팅은 기술 문제가 아니라 정책 문제다. 어떤 태스크에 어떤 모델을 쓸지는 결국 팀 리드가 명시적으로 설계해야 할 판단이다. 이걸 에이전트에게 위임하면, 에이전트는 판단하지 않는다—그냥 가장 강한 모델로 보낸다. 여기서부터가 문제다. 세 소스에서 공통적으로 도출되는 설계 축은 명확하다: 태스크 분류 기준, 에스컬레이션 상한, 그리고 감사 로그. 순서대로 짚어보자.
1. 태스크 분류 기준: 실패를 누가 잡는가로 나눠라
직관적으로 '어려운 태스크'와 '쉬운 태스크'를 나누고 싶겠지만, 그 기준은 애매하고 주관적이다. 실용적인 분류 기준은 하나다: 이 태스크의 잘못된 출력을 누가 잡는가? dev.to의 Cost-Aware Router 글은 이걸 3티어로 정리한다.
| 티어 | 태스크 유형 | 실패 탐지자 | 라우팅 |
|---|---|---|---|
| 1 | 기계적 변환, 테스트/린터로 검증 가능 | CI | 무료/최저가 모델 |
| 2 | 단일 파일 로컬 추론 | 빠른 코드 스킴 | 무료/저가 모델 |
| 3 | 멀티파일 설계, 동시성, 보안, 비가역 변경 | 인간 리뷰 | 최강 모델 |
핵심 논리는 이렇다: 기계적으로 검증 가능한 태스크에서 틀린 답변은 테스트 스위트가 잡는다. 설계 판단에서 틀린 답변은 당신이 잡는다—리뷰 비용이 모델 비용보다 훨씬 크다. 따라서 최적화 대상은 모델 품질이 아니라 리뷰 비용이다. 약한 모델이 동시성 버그를 그럴싸하게 틀리게 고쳐주면, 그걸 잡는 데 드는 시간이 모델 비용의 몇 배를 날린다.
분류기를 처음부터 ML로 만들 필요는 없다. 감사 가능한 휴리스틱으로 시작하면 충분하다. race, auth, migrat, refactor across 같은 키워드가 보이면 티어 3, 수정 파일이 1개면 티어 2, 테스트가 있으면 티어 1—이 정도 규칙만으로도 대부분의 볼륨을 저렴하게 처리할 수 있다. 중요한 건 이 분류 결정이 명시적이고, 로깅되고, 변경 가능해야 한다는 것이다. 직감으로 결정하는 순간 데이터가 사라진다.
한 가지 더: 분류기를 코드에 하드코딩하지 말고 Git으로 관리되는 JSON 정책 파일로 분리하라. 두 번째 소스가 강조하는 포인트다. 라우팅 규칙이 diffable하고 reviewable한 파일이 되는 순간, 팀 리드는 비용 정책을 코드 리뷰하듯 검토할 수 있다. PR로 정책 변경을 제안하고, blame으로 누가 언제 기준을 바꿨는지 추적할 수 있다.
2. 에스컬레이션 상한: 재시도 루프는 느린 지출 폭탄이다
라우팅 설계에서 가장 흔한 실수는 에스컬레이션에 상한을 두지 않는 것이다. 저렴한 모델이 실패하면 비싼 모델로 올리고, 그것도 실패하면... 다시 시도? 이 루프는 결국 최고가 모델에 도달하는 느린 경로일 뿐이다. 게다가 실패 로그도 없고, 왜 에스컬레이션됐는지도 추적이 안 된다.
설계 원칙은 간단하다: 티어당 시도 횟수는 1회, 최상위 티어에서 실패하면 인간 이슈로 전환. 두 번째 소스의 정책 파일은 이걸 "attempts_per_tier": 1, "on_exhaustion": "open_issue_for_human"으로 명시한다. 에스컬레이션은 상한이 있는 폭포수여야 한다—무한 루프가 아니라.
에스컬레이션 방향도 중요하다. 분류기가 확신하지 못하면 위가 아니라 아래에서 시작해야 한다. 저렴한 모델에서 시작해서 게이트(테스트/린터)를 통과하지 못하면 위로 올리는 구조가, 비싼 모델에서 시작해서 태스크가 사실 쉬웠다는 걸 나중에 발견하는 것보다 훨씬 낫다. 실패 방향은 위로, 기본값은 아래로.
여기서 하나의 안전장치가 추가된다: 게이트는 모델이 아니라 결정론적 도구여야 한다. 세 번째 소스가 이를 가장 명확하게 못 박는다—"LLM이 자신의 출력을 스스로 평가하게 하지 말라. LLM은 정확도와 무관하게 자신감을 보고한다." 테스트 스위트, 파서, 스키마 검증기, 정규식—환각하지 않는 것만 게이트로 쓸 수 있다. LLM-as-judge를 게이트로 쓰는 순간 비용 문제를 레이턴시까지 얹어서 재현하는 것이다.
3. 감사 로그: 추정이 아니라 측정으로 운영하라
라우팅 설계의 세 번째 축은 가장 과소평가된다. 분류기와 에스컬레이션 규칙을 만들었다면, 그 결정들이 실제로 옳았는지 측정하는 루프가 없으면 반쪽짜리 시스템이다. 세 소스 모두 공통적으로 강조하는 것이 로그다.
최소한의 감사 로그는 각 태스크마다 이것을 기록해야 한다: 어떤 티어로 라우팅됐는가, 에스컬레이션이 발생했는가, 게이트를 통과했는가, 소요 시간은 얼마인가. 이 로그가 몇 주 쌓이면 비로소 실질적인 질문에 답할 수 있다.
- 태스크 유형별 fallback 비율: 데이터 포맷 변환이 저렴한 모델에서 92% 통과하면 그 유형은 저가 라우팅이 합리적이다. 멀티파일 리팩터가 60% 실패하면 저가 모델은 그 유형에서 거짓 경제다—첫 시도 비용 + 에스컬레이션 레이턴시를 합산하면 처음부터 비싼 모델 쓰는 것보다 비싸진다.
- 태스크 유형별 실효 비용: 저가 모델 호출 1회 성공과 저가 실패 + 고가 폴백의 총 비용을 태스크 유형별로 계산하면, '어떤 유형을 어디서 끊어야 하는가'가 추정이 아닌 데이터로 나온다.
- 새 모델 출시 시 회귀 테스트: 로그에 프롬프트 핑거프린트를 남겨두면, 새 모델이 나왔을 때 기존 태스크 코퍼스를 재실행해서 fallback 비율 변화를 비교할 수 있다. 어떤 공개 벤치마크보다 당신의 실제 워크로드에 정직하다.
그리고 로그를 쌓기 전에 라우팅을 자동화하지 말라. 세 소스 모두 공통적으로 권고하는 것이 shadow mode 먼저다: 분류기가 태스크에 레이블을 붙이되, 실제 라우팅은 기존 방식대로 유지하면서 1~2주치 로그를 먼저 쌓는다. '내 분류기가 gratis로 분류한 태스크 중 나중에 재작업이 필요했던 비율은 얼마인가?' '전체 볼륨 중 저가 티어 비율이 40% 미만이면 기준이 너무 보수적인 게 아닌가?'—이 숫자를 먼저 확인하고 자동화 스위치를 켜는 것이다.
도입 전에 솔직하게 확인할 것들
모델 라우팅이 모든 팀에 유효하지는 않다. 세 소스가 공통으로 인정하는 한계들이다.
테스트가 없으면 전제가 무너진다. 게이트가 결정론적 도구여야 한다는 원칙은, 결정론적 도구가 존재할 때만 성립한다. 테스트도 린터도 없는 코드베이스에서 라우팅을 도입하는 건 로그만 쌓고 판단은 여전히 감으로 하는 것이다. 라우팅보다 테스트 스위트가 먼저다.
태스크 거의 전부가 티어 3이면 절약할 게 없다. 보안 크리티컬 시스템, 커널 코드, 의료 소프트웨어—"쉬운 태스크"가 없는 도메인에서는 정책 파일에서 하위 두 줄을 지우고 처음부터 최강 모델로 시작하는 게 맞다.
동기식 레이턴시 예산이 빡빡하면 캐스케이드는 독이다. 저가 모델 실패 + 고가 모델 재시도는 벽시계 기준 2배 레이턴시를 만든다. 개발자가 자동완성을 기다리는 인터랙티브 경로에 이 구조를 넣으면 안 된다. 백그라운드 배치 작업과 비동기 파이프라인에만 적용하고, p99 숫자가 나오기 전까지는 인터랙티브 경로는 단일 모델 고정이 낫다.
마지막으로 하나. 세 소스 모두 무료 모델 티어를 실험 인프라로 활용한다는 점을 언급하지만(MonkeyCode 기반 실험), 무료 티어를 아키텍처에 하드코딩하지 말라는 경고도 공통적으로 담고 있다. 엔드포인트는 설정으로, 모델 ID는 변수로—무료 티어가 사라지거나 레이턴시가 튀면 에스컬레이션 규칙이 자동으로 상위 티어로 올려야 한다. 공급자의 관대함을 아키텍처 보장으로 착각하면 안 된다.
요약하면 이렇다. AI 코딩 에이전트의 모델 라우팅은 엔지니어링 문제가 아니라 운영 설계 문제다. 분류 기준을 명시적으로 만들고, 에스컬레이션에 상한을 두고, 감사 로그로 그 판단을 측정하라. 이 세 가지를 설계하지 않으면 에이전트는 비용을 줄이는 게 아니라—비용을 숨긴다.