Jev AI — 에이전트 라우팅과 검증에 넣어본다면 (2/3)
Router도 결국 모델 호출이다
에이전트 아키텍처를 설계하다 보면 거의 항상 마주치는 질문이 있다. "이 요청을 어떤 Tool·Agent로 보낼까?" 이 질문에 답하는 로직을 Router라고 부르는데, 보통 이것도 LLM이 맡는다. 문제는 라우팅 판단 하나 하려고 매번 큰 Reasoning 모델을 호출하면, 라우팅 자체가 병목이 된다는 점이다.
실제로 노가리를 만들 때 비슷한 문제를 겪었다. 새 방 제안이 들어오면 "기존 방 중에 의미상 겹치는 게 있는가"를 판단해야 하는데, 지금은 기존 주제 목록을 통째로 Claude에게 넘겨서 판단시킨다. 동작은 하지만, 방 제안 하나당 모델 호출 하나가 붙는 구조다. Jev가 노리는 게 바로 이 지점이다 — "방 A와 방 B가 같은 주제인가"처럼 선택지가 제한된 판단은, 꼭 Claude 수준의 모델이 아니어도 될 수 있다는 것.
Code → Jev → LLM/Agent로 역할을 나눠보면
Jev를 끼워 넣으면 요청 처리 구조가 이렇게 재배치될 수 있다.
| 계층 | 담당하는 일 | 예시 |
|---|---|---|
| Code | 명확한 규칙 | HTTP 상태 확인, 스키마 검증 |
| Jev | 애매하지만 빠른 판단 | 분류, 라우팅, 채점, 모더레이션 |
| LLM | 깊은 추론과 생성 | 코드 작성, 문서화, 리서치 |
| Agent | 장기 작업 수행 | 여러 Tool을 엮어 목표 달성 |
이 표를 보면서 내 프로젝트 몇 개를 다시 떠올려봤다.
- 매치다의 "채용공고-내 프로필 매칭 점수"는 사실상 Score 판단이다. 지금은 Claude API로 점수를 매기는데, 매칭 점수 자체는 복잡한 글쓰기가 아니라 "이 공고와 내 경력이 얼마나 겹치는가"라는 좁은 판단이다. 공고 하나하나에 큰 모델을 쓰는 대신, 1차로 Jev 같은 모델이 점수를 매기고 애매한 구간(예: 0.4~0.6)만 큰 모델로 재검토하는 구조가 가능할 것 같다.
- 노가리의 댓글 2단계 필터(정규식 → LLM)는 사실 Noul에 가깝다. "개인정보 포함?", "욕설?", "스팸?"을 각각 독립된 Yes/No로 쪼개면, 지금처럼 LLM 하나가 한 번에 다 판단하는 것보다 더 세밀하게 신고 큐를 나눌 수 있을 것 같다.
Skill/MCP 구조와 맞물리는 지점
요즘 에이전트 아키텍처는 모든 기능을 Agent로 만들기보다, Skill이나 MCP Tool을 호출하는 방식을 많이 쓴다. 이 환경에서도 Router 문제는 똑같이 발생한다 — 요청이 들어왔을 때 "이건 Skill로 처리할까, MCP Tool을 부를까, 아니면 별도 Research Agent로 넘길까"를 정해야 한다. 이 선택이 유한한 목록 중 하나를 고르는 Choice 문제라면, 매번 Orchestrator가 큰 모델을 호출해서 고민하는 대신 Jev 같은 가벼운 판단 모델을 앞단에 세우는 구조가 자연스럽다.
이걸 요청 하나가 들어왔을 때의 흐름으로 다시 그려보면 이렇다.
request
↓
jev.choose(["skill:release", "mcp:github", "agent:research"])
↓
┌──────────────┬──────────────┬─────────────────┐
confidence 0.91 confidence 0.05 confidence 0.04
↓
release Skill 바로 실행
confidence가 한쪽으로 확실히 쏠려 있으면 Orchestrator가 더 고민할 필요 없이 바로 해당 Skill이나 Tool을 실행하면 된다. 반대로 세 선택지의 confidence가 비슷하게 애매하면, 그때는 Jev가 대신 판단해주지 않고 Orchestrator가 더 큰 모델에게 "이 요청, 정확히 뭘 원하는 거야?"라고 되물어야 한다는 신호로 받아들이면 된다. 즉 Jev를 끼워 넣는다고 해서 애매함 자체가 사라지는 건 아니고, "애매한 케이스를 더 싸고 빠르게 걸러내는" 역할을 하는 거다.
결과를 검증하는 데도 쓸 수 있다
Jev를 입력 라우팅에만 쓸 이유는 없다. Agent가 작업을 끝낸 뒤 결과를 검증하는 단계에도 붙일 수 있다. "요청을 충족했는가?", "보안 위험이 있는가?" 같은 질문은 Build나 Unit Test처럼 명확하게 확인할 수 있는 건 아니지만, 그렇다고 사람이 한 건 한 건 다 봐야 할 정도로 복잡하지도 않다. 컴파일러·테스트·정적 분석으로 확인할 수 있는 건 그쪽에 맡기고, 애매한 판단만 Jev 같은 모델에게 맡기는 식으로 역할을 나눌 수 있다.
실제로 적용한다면 이런 흐름이 될 것 같다.
- Agent가 PR이나 변경 사항을 만든다
- Code 레벨 검증(빌드, 테스트, lint)을 먼저 돌린다
- 통과한 것 중에서 "요청 의도와 맞는가" 같은 애매한 판단만 Jev 같은 모델에게 넘긴다
- confidence가 낮게 나온 것만 사람이나 큰 모델이 다시 본다
Build나 Test로 떨어지는 결정적인 오류는 애초에 Jev까지 갈 필요가 없다는 게 핵심이다. 지금 나는 커밋 단위 작업을 맡길 때 결과물을 사람이 직접 눈으로 훑어보는데, 리뷰할 PR 개수가 지금보다 훨씬 많아진다면 "이 변경이 원래 요청한 범위를 벗어나지 않았는가" 정도의 1차 거름망을 Jev 같은 모델에게 맡기고, 거기서 걸러진 것만 내가 보는 구조가 더 현실적일 것 같다.
Guardrail로도 같은 자리에 들어간다
Router와 Verification 사이, 즉 입력을 받자마자 거치는 Guardrail도 같은 패턴이다. 사용자 입력이 위험한지, 프롬프트 인젝션 시도인지를 매번 큰 모델에게 먼저 물어보는 구조는 입력 하나당 모델 호출이 최소 두 번(Guardrail + 실제 처리) 필요하다는 뜻이다. 이 앞단 Guardrail이야말로 복잡한 추론이 필요 없는, 전형적인 Choice/Noul 문제에 가깝다. "이 입력은 안전한가/위험한가/판단 불가"처럼 선택지가 제한돼 있고, 틀렸을 때의 리스크는 크지만 판단 자체의 난이도는 높지 않은 영역이기 때문이다.
다음 편에서는 이 모든 구조에서 정말 중요한 건 "판단 모델이 똑똑한가"가 아니라 "그 판단을 얼마나 믿을 수 있는지"라는 이야기를 해보려 한다. Confidence를 어떻게 다루느냐에 따라, 같은 모델이라도 자동화 가능한 범위가 완전히 달라진다.
backtodev
40대 PM, 다시 개발자로 돌아갑니다. 실패하고 배우며 성장하는 기록.