fos-blog/study
01 / 홈02 / 카테고리03 / 시리즈
01 / 홈02 / 카테고리03 / 시리즈

카테고리

  • AI 페이지로 이동
    • RAG 페이지로 이동
    • agent 페이지로 이동
    • claude-code 페이지로 이동
    • harness 페이지로 이동
    • llm 페이지로 이동
    • ops 페이지로 이동
    • practice 페이지로 이동
  • algorithm 페이지로 이동
    • Alias Method: 가중치 랜덤 선택을 전처리 O(n), 추출 O(1)로 바꾸기
    • Welford's Online Algorithm: 값을 저장하지 않고 평균과 분산 계산하기
  • architecture 페이지로 이동
    • distributed-systems 페이지로 이동
    • domain 페이지로 이동
    • evolution 페이지로 이동
    • patterns 페이지로 이동
  • database 페이지로 이동
    • milvus 페이지로 이동
    • mysql 페이지로 이동
    • opensearch 페이지로 이동
    • postgresql 페이지로 이동
    • qdrant 페이지로 이동
    • redis 페이지로 이동
    • vespa 페이지로 이동
    • DB Connection Pool Saturation과 Thread Pool 격리
    • 커넥션 풀 크기는 얼마나 조정해야 할까?
    • gaps and islands: SQL 창 함수로 이어진 구간 찾기
    • MyBatis 기본기 — XML Mapper, resultMap, 동적 SQL, 운영 패턴 정리
    • MyBatis와 JPA/Hibernate 트레이드오프 — 레거시 백엔드를 다루는 시니어 관점
    • 한국어 형태소 분석기 Nori vs Lindera — OpenSearch에서 Milvus로 갈 때 어휘 검색은 유지되나
    • 정규화와 역정규화: 무결성과 조회 비용 사이의 선택
    • 벡터 DB 5종, 아키텍처는 어떻게 다른가
    • 벡터 DB 5종을 실제로 벤치마크했다 — 같은 recall에서 QPS는 얼마나 갈리나
    • 벡터 DB 어떻게 고를까 — OpenSearch · Milvus · Qdrant · Vespa · pgvector 비교
    • 벡터 DB를 실제로 도입한 사례 — 빅테크 프로덕션
  • devops 페이지로 이동
    • docker 페이지로 이동
    • k8s 페이지로 이동
    • Envoy Proxy
    • Graceful Shutdown
    • 종료 신호는 어디서 멈추는가
  • http 페이지로 이동
    • HTTP Connection Pool
    • HTTPS와 TLS: 핸드셰이크, 인증서, 종료 지점
  • java 페이지로 이동
    • concurrency 페이지로 이동
    • jdbc 페이지로 이동
    • spring 페이지로 이동
    • spring-batch 페이지로 이동
    • testing 페이지로 이동
    • Alpine 이미지의 Java 에서 링크 바꿔치기(TOCTOU)를 막지 못하는 이유
    • Java 동시성 락 정리 — 커머스 메뉴/프로모션 정책 캐시 갱신 관점
    • JVM 튜닝 실전: 메모리 구조부터 Virtual Threads, GC 튜닝, 프로파일링까지
    • 로그에 traceId 남기기 — MDC 부터 OpenTelemetry 까지
    • Java StampedLock — 읽기 폭주에도 쓰기가 밀리지 않는 락
    • Virtual Thread와 Project Loom
  • javascript 페이지로 이동
    • typescript 페이지로 이동
    • AbortController
    • Async Iterator와 제너레이터
    • CommonJS와 ECMAScript Modules
    • 제너레이터(Generator)
    • Http Client
    • Node 백엔드 운영 패턴 — Streams 백프레셔, pipe/pipeline, 멱등성 vs 분산 락
    • Node.js
    • `setImmediate()`
  • kafka 페이지로 이동
    • Kafka 클러스터 아키텍처: Broker, KRaft Controller와 복제
    • Kafka 기본 개념: Topic, Partition, Offset과 Segment
    • Kafka 실전 설계: 파티션 전략, 컨슈머 그룹, 전달 보장, 재시도, 순서 보장 트레이드오프
    • Kafka 파티션·리밸런스·컨슈머 지연 운영
    • Kafka를 로그로 이해하기: 복제, 재처리, 상태와 데이터 통합
    • Spring Kafka 컨슈머 오프셋 커밋과 트랜잭션 정렬: AckMode, manual ack, 멱등 처리
  • linux 페이지로 이동
    • fsync — 리눅스 파일 동기화 시스템 콜
    • SSH forced command 로 배포 키가 실행할 수 있는 명령 제한하기
  • mlops 페이지로 이동
    • llm-serving 페이지로 이동
    • model-router 페이지로 이동
    • Python CUDA 버전 생태계 — nvidia-smi, nvcc, pip, conda가 다 다른 버전을 말하는 이유
    • GPU 컨테이너의 CUDA 버전 호환성 — nvidia-smi부터 이미지 다이어트까지
    • Kubernetes GPU 노드에서 /run tmpfs가 꽉 차서 Pod가 안 뜰 때
    • GPU·CUDA·MPS 기초 — 자바 백엔드 개발자가 처음 만나는 그림
    • Multi-process GPU 워크로드 — 자바 ThreadPool 사용자가 만나는 모델 차이
    • ML 서비스 성능 분석 워크플로 — 자바 백엔드 트러블슈팅과 다른 점
    • 한 GPU 를 여러 프로세스가 나눠 쓰기 — Time-Slicing 과 MPS
  • network 페이지로 이동
    • Connection reset by peer는 누가 보낸 걸까 — 리버스 프록시 홉마다 TCP 연결은 따로 논다
    • L2(스위치)와 L3(라우터)의 역할 차이
    • L4와 VIP(Virtual IP Address)
    • IP Subnet
  • observability 페이지로 이동
    • Observability 입문: 시니어 백엔드가 장애를 탐지하고 대응하는 방식
    • K8s 위 Spring Boot 앱의 메트릭 수집
  • python 페이지로 이동
    • Python async/await — CompletableFuture·Reactor 와 다른 점, 그리고 blocking I/O 함정
    • Python 의존성 관리 — Java Maven/Gradle 사용자가 만나는 첫 충격
    • FastAPI 기초 — Spring Boot 사용자가 빠르게 익히는 법
    • Java 개발자를 위한 Python 심화 — OOP·데코레이터·컨텍스트 매니저
    • PyTorch 기초 — 텐서, 디바이스, 그리고 모델 로딩이 무거운 이유
    • Java 개발자를 위한 Python 문법 핵심
    • ThreadLocal 에서 contextvars 로 — Python 의 요청 컨텍스트 전파
    • OCR 동작 원리 — Layout · Text · Post-process 3단계
    • Python 서버의 RSS가 줄지 않는 이유: CPython, gc.collect(), malloc_trim
  • rabbitmq 페이지로 이동
    • RabbitMQ Basics — 실전 백엔드 관점에서 정리하는 메시지 브로커 기본기
    • RabbitMQ vs Kafka — 백엔드 메시징 선택 기준과 실전 운영 관점
  • resume 페이지로 이동
    • 경험 및 경력기술서
    • 김병태 경력기술서
    • 김병태 포트폴리오
  • task 페이지로 이동
    • ai-service-team 페이지로 이동
    • nsc-slot 페이지로 이동
    • personal-projects 페이지로 이동
    • sb-dev-team 페이지로 이동
    • the-future-company 페이지로 이동
  • thinking 페이지로 이동
    • 자기주도 학습: 질문에서 시작해 글로 검증하기
    • 좋은 일을 넘어 중요한 일을 하는 법
FOS-BLOG · FOOTERall systems normal·v0.1 · 2026.04.27·seoul, kr
Ffos-blog/study

개발 학습 기록을 정리하는 블로그입니다. 공부하면서 기록하고, 기록하면서 다시 배웁니다.

visitors
01site
  • Home↗
  • Posts↗
  • Categories↗
  • Glossary↗
  • About↗
02policy
  • 소개/about
  • 개인정보처리방침/privacy
  • 연락처/contact
03categories
  • AI↗
  • Algorithm↗
  • DB↗
  • DevOps↗
  • Java/Spring↗
  • JS/TS↗
  • React↗
  • Next.js↗
  • System↗
04connect
  • GitHub@jon890↗
  • Source repositoryjon890/fos-study↗
  • RSS feed/rss.xml↗
  • Newsletter매주 1 회 · 한 편의 글→
© 2026 FOS Study. All posts MIT-licensed.
built with·Next.js·Tailwind v4·Geist·Pretendard·oklch
fos-blog/mlops/어느 모델로 보낼지 무엇으로 정하는가
mlops

어느 모델로 보낼지 무엇으로 정하는가

"싼 모델로 보내 비용을 줄인다" 는 문장에는 빠진 것이 있다. 싼 모델로 보내도 되는 요청인지를 누가 판단하는가, 그리고 그 판단 자체에 얼마가 드는가다. 결론부터 적는다. 판단 방식은 넷이고, 판단에 드는 시간은 대부분의 경우 병목이 아니다. 비용을 정하는 것은 판단 시간이 아니라 그 판단이 고른 모델이다. 넷은 배타적이지 않다. 규칙으로 큰 갈래를 먼...

2026.09.08·8 min read·70 views·SERIES · Model Router · 2/8

Model Router 시리즈 2번이다. 앞 글 Model Router 란 무엇인가에서 결정 계층과 Gateway 계층을 갈랐다. 이 글은 그중 결정 계층이 요청 하나를 보고 어느 모델로 보낼지 정하는 방법을 다룬다.

"싼 모델로 보내 비용을 줄인다" 는 문장에는 빠진 것이 있다. 싼 모델로 보내도 되는 요청인지를 누가 판단하는가, 그리고 그 판단 자체에 얼마가 드는가다.

결론부터 적는다. 판단 방식은 넷이고, 판단에 드는 시간은 대부분의 경우 병목이 아니다. 비용을 정하는 것은 판단 시간이 아니라 그 판단이 고른 모델이다.

판단 방식 넷

방식동작
규칙태그, 호출자, 요청 메타데이터로 미리 정한 배포 그룹에 매핑한다
임베딩질문을 벡터로 바꿔 최근접 중심점이나 가벼운 분류기로 난이도와 범주를 판정한다
분류 모델별도로 학습한 분류기가 난이도와 의도와 도메인을 예측한다
계단식싼 모델에 먼저 보내고 응답 신뢰도가 기준을 넘으면 그대로 쓰고, 못 넘으면 상위 모델로 다시 보낸다

넷은 배타적이지 않다. 규칙으로 큰 갈래를 먼저 가르고 그 안에서 분류 모델을 쓰는 조합이 가능하다.

규칙

가장 먼저 만들게 되는 형태다. LiteLLM 은 배포에 태그를 붙이고 호출하는 쪽이 x-litellm-tags 헤더로 태그를 보내는 방식을 제공한다. 요청 본문을 읽지 않고 헤더와 호출자 정보만 보므로 판단이 사실상 무료다.

한계는 분명하다. 같은 서비스가 보내는 요청 안에서 난이도가 갈리면 규칙이 그것을 구분할 수 없다. 호출하는 쪽이 자기 요청의 난이도를 판정해 태그를 붙여야 하고, 그러면 판단이 다시 애플리케이션으로 흩어진다.

임베딩

질문을 벡터로 바꿔 미리 만들어 둔 범주 중심점 중 가장 가까운 것을 고르거나, 그 벡터를 입력으로 받는 가벼운 분류기를 태운다. 요청 본문을 실제로 읽는 첫 방식이라 규칙보다 정밀하지만, 임베딩 모델을 호출하는 시간이 붙는다.

분류 모델

임베딩 뒤에 분류기를 붙이는 대신, 텍스트를 바로 받아 난이도와 의도와 도메인을 예측하도록 학습한 모델을 둔다. BERT 계열의 작은 encoder 모델이 이 자리에 쓰인다.

KT 의 Model Orchestrator 가 이 축을 넷으로 나눈 사례다. 요청을 Task 와 Domain 과 Level 과 Capability 로 분류해 모델을 고른다. 난이도 하나로 고르지 않고 축을 나눈 것이 이 사례에서 읽을 지점이다.

계단식

싼 모델을 먼저 부르고 응답이 쓸 만하면 거기서 끝낸다. 쓸 만하지 않으면 상위 모델을 다시 부른다. 요청 본문을 판정하지 않고 응답을 판정하므로 앞의 셋과 성격이 다르다.

대신 대가가 있다. 상위 모델로 올라가는 요청은 싼 모델 호출 비용을 이미 치른 뒤에 비싼 모델 비용을 또 낸다. 싼 모델에서 끝나는 비율이 충분히 높지 않으면 계단식이 오히려 비싸진다.

판단에 드는 시간

조건 없이 인용할 수 있는 숫자가 아니다. 하드웨어와 입력 토큰 길이에 따라 값이 크게 갈리므로, 아래 표는 측정 조건을 함께 읽어야 한다.

라우터측정값측정 조건
규칙1ms 미만벤치마크 조건이 명시되지 않은 일반 서술이다
임베딩5에서 20msall-MiniLM-L6-v2 기준. 단일 GPU 에서 초당 약 14,200 문장. GPU 모델명은 원 자료에 없다
DistilBERT 분류기P95 7.3msNVIDIA T4, 단일 배치, 200 토큰
ModernBERT 149M 분류기P50 22.5ms, P95 23.1ms같은 조건
ModernBERT base 도메인 분류중앙값 60ms, P99 120msNVIDIA A100

이 값들을 비교할 상대는 모델 호출 자체의 응답 시간이다. 그 값은 모델과 출력 토큰 수와 하드웨어로 갈리므로 하나의 범위로 적을 수 없고, 조건 없이 인용할 수 있는 값을 찾지 못했다. 다만 판단 지연 쪽이 위 표대로 수십 ms 안에 들어가는 반면 모델 호출은 초 단위로 가는 경우가 흔하다. 그래서 판단 방식을 고를 때 지연을 첫 기준으로 두면 판단이 어긋난다. 자기 트래픽에서 두 값을 함께 재 보면 이 비율을 확인할 수 있다.

"분류 모델은 50에서 100ms" 라는 요약을 블로그에서 흔히 보는데, 1차 벤치마크 근거를 찾지 못했다. 위 실측값과도 맞지 않는다. 이 글에서는 그 값을 쓰지 않는다.

계단식만 성격이 다르다. 계단식에서 늘어나는 것은 판단 시간이 아니라 모델 호출 횟수다. 상위 모델로 올라가는 요청은 싼 모델의 전체 응답 시간을 먼저 다 쓴 뒤에 비싼 모델을 부른다. 넷 중 지연을 실제로 크게 늘리는 것은 이쪽이다.

계단식에서 신뢰도를 무엇으로 재는가

"신뢰도가 낮다" 를 무엇으로 정하느냐가 계단식의 핵심이다. 이 판정이 틀리면 상위 모델로 올려야 할 요청을 그대로 내보내거나, 올리지 않아도 될 요청을 올린다.

신호판정
토큰 마진다음 토큰 예측에서 상위 두 로짓의 차이. 크면 고신뢰
토큰 확률답변 토큰의 생성 확률이 낮으면 저신뢰
자기 일관성여러 번 샘플링해 답이 갈리는지 본다. 응답 간 유사도가 낮으면 저신뢰
엔트로피의미가 다른 답변 무리에 대한 분포의 불확실성
학습된 품질 추정기응답의 정답 여부와 재샘플링 일관성을 예측하도록 학습한 함수

토큰 마진은 원시 값 그대로는 약한 신호다. 따로 떼어 둔 보정 세트에 isotonic 보정을 적용하면 거의 최적의 라우팅 점수가 된다는 결과가 있다. 값을 그냥 임계치와 비교하는 것과 보정을 거치는 것 사이에 차이가 있다는 뜻이다.

자기 일관성은 정확하지만 비싸다. 같은 요청을 여러 번 샘플링해야 하므로 계단식으로 아끼려던 비용을 판정 단계에서 다시 쓴다.

FrugalGPT 는 이 구조를 3단으로 정리했다. pre-router 가 처음 모델을 고르고, quality estimator 가 응답을 평가하고, escalation policy 가 수용할지 상위 모델로 넘길지 정한다. 직접 계단식을 만들 때 이 셋을 각각 무엇으로 채울지가 설계 항목이 된다.

라우터를 학습시키는 방식

규칙과 임계치를 사람이 정하는 대신, 라우팅 판단 자체를 학습 문제로 두는 접근이 있다.

RouteLLM 은 특정 질의에서 강한 모델이 약한 모델보다 나은 응답을 낼 확률을 예측하는 라우터를 학습한다.

항목내용
학습 데이터Chatbot Arena 의 사람 선호 비교 8만 건. 16자 미만 프롬프트를 걸러 64개 모델 간 6만 5천 쌍으로 정제
구조BERT 분류기와 행렬 분해 두 갈래
결과논문이 쓴 대표 벤치마크에서 2배 이상 비용 절감. 어느 벤치마크인지는 요약 자료에 없다

여기서 읽을 것은 절감 폭보다 갈린 지점이다. Arena 데이터만으로는 BERT 분류기가 저데이터 환경에서 무작위에 가까운 성능을 냈다. 같은 조건에서 행렬 분해는 GPT-4 호출 절반으로 50% 성능 향상 비율에 도달했다. GPT-4 를 judge 로 써 데이터를 늘린 뒤에는 모든 라우터가 나아졌다.

데이터가 적을 때 무엇이 먼저 무너지는지가 이 연구의 실용적인 교훈이다. 학습된 라우터를 도입할 때 모델 구조를 고르는 문제보다 학습 데이터를 얼마나 모을 수 있는지가 먼저 걸린다.

vLLM Semantic Router

2025년 9월 공개된 vllm-project 산하 프로젝트다. 학습된 분류기를 라우팅 계층에 넣은 오픈소스 구현이라 구조를 참고할 수 있다.

항목내용
정체이기종 LLM 추론을 위한 프로그래밍 가능한 Mixture-of-Models 라우터
위치Envoy External Processor 로 클라이언트와 모델 백엔드 사이에 놓인다
분류ModernBERT 기반 분류기가 질의의 의도와 복잡도를 잰다. 단순한 것은 빠른 경로로, 복잡한 것은 추론 모드로
부가prompt guarding 과 PII 탐지가 내장돼 있다

보고된 결과는 vLLM 직접 추론 대비 MMLU-Pro 정확도 10.2%p 상승, 응답 지연 약 48% 감소다. 이 수치는 조건을 붙여 읽어야 한다. 지연 감소폭이 문서마다 47.1% 와 48.5% 로 다르게 적혀 있고, 하드웨어와 모델 조합이 원문에 명시돼 있지 않다.

분류기는 지금 라우터 안에 고정돼 있고, 갈아 끼울 수 있게 만드는 것이 앞으로의 과제로 적혀 있다.

라우팅 품질을 어떻게 재는가

라우터를 바꿨을 때 나아졌는지를 판정할 방법이 없으면 정책을 조정할 수 없다. 공개된 벤치마크가 셋 있다.

벤치마크담는 것
RouterBench11개 모델, 7개 태스크, 사전 계산한 추론 결과 40만여 건
RouterEval8,500개 이상 모델, 12개 벤치마크, 2억 건 이상 성능 기록
LLMRouterBench21개 데이터셋, 33개 모델, 10개 라우팅 방법

RouterBench 는 추론 결과를 미리 계산해 둔다. 라우팅 방법을 바꿀 때마다 모델을 다시 부르지 않고 표에서 값을 찾아 쓰므로 비교 실험이 싸진다.

RouterBench 는 AIQ 라는 지표를 쓴다. 비용과 품질 곡선의 정규화된 곡선 아래 면적이고, 높을수록 비용 대비 품질 균형이 좋다. 단일 지점의 정확도 하나로 라우터를 비교할 수 없기 때문에 곡선 전체를 하나의 값으로 압축한 것이다.

평가 축은 둘로 갈린다.

  • 효과성은 질의가 최고 성능 후보로 갔는지를 직접 잰다
  • 효율성은 비용과 지연을 잰다

자체 라우터를 만들 때도 이 둘을 따로 재야 한다. 비용만 줄고 효과성이 무너진 상태를 하나의 지표로는 알아볼 수 없다.

정리

  • 판단 방식은 규칙, 임베딩, 분류 모델, 계단식 넷이고 배타적이지 않다. 규칙으로 갈래를 가른 뒤 그 안에서 분류 모델을 쓰는 조합이 흔하다.
  • 판단 지연은 대부분 전체 응답 시간의 몇 % 수준이다. 넷 중 지연을 실제로 크게 늘리는 것은 계단식이고, 늘어나는 것은 판단 시간이 아니라 모델 호출 횟수다.
  • 계단식의 설계 항목은 신뢰도를 무엇으로 재는지다. 토큰 마진은 보정을 거쳐야 쓸 만하고, 자기 일관성은 정확하지만 재샘플링 비용이 든다.
  • 학습된 라우터를 도입할 때 먼저 걸리는 것은 모델 구조가 아니라 학습 데이터의 양이다. RouteLLM 에서 데이터가 적을 때 BERT 분류기가 먼저 무너졌다.
  • 라우터 성능은 효과성과 효율성을 따로 재야 한다. 비용만 줄고 응답 품질이 무너진 상태를 하나의 지표로는 구분할 수 없다.

다음 편

다음 글에서는 라우터를 실제로 붙였을 때 만나는 제약을 다룬다. 컨텍스트 한도가 라우팅 대상 중 가장 작은 모델에 맞춰지는 문제, 대상 목록을 고정해야 하는 이유, 어느 모델이 응답했는지 사후에 되짚는 방법, 그리고 캐시와 라우팅이 서로를 방해하는 구간이 주제다.

모델을 골라주는 계층이 대신 가져오는 제약으로 이어진다.

참고 링크

  • RouteLLM 논문
  • LMSYS. RouteLLM 소개
  • RouterBench 논문
  • RouterEval 논문
  • Dynamic Model Routing and Cascading Survey
  • vLLM Semantic Router 블로그
  • vllm-project/semantic-router
  • Red Hat. vLLM Semantic Router
  • LiteLLM Tag Based Routing
  • KT. Model Orchestrator
on this page
  • 01판단 방식 넷
  • 규칙
  • 임베딩
  • 분류 모델
  • 계단식
  • 02판단에 드는 시간
  • 03계단식에서 신뢰도를 무엇으로 재는가
  • 04라우터를 학습시키는 방식
  • vLLM Semantic Router
  • 05라우팅 품질을 어떻게 재는가
  • 06정리
  • 07다음 편
  • 08참고 링크
tags
#Model Router#LLM 서빙#라우팅#study📚 Model Router
← PREVIOUSModel Router 란 무엇인가NEXT →모델을 골라주는 계층이 대신 가져오는 제약

이런 글도

  • mlops

    같은 문제를 회사마다 다른 층에서 푼다

    2026.09.08
  • mlops

    첫 토큰이 나간 뒤에는 재시도할 수 없다

    2026.09.08
  • mlops

    캐시를 보고 인스턴스를 고른다

    2026.09.08
  • mlops

    모델을 골라주는 계층이 대신 가져오는 제약

    2026.09.08

댓글 (0)