LLM은 마지막 수단으로: 7B 모델을 아주 작은 Go 분류기로 교체한 사례
요약
프로덕션 환경에서 LLM의 비용과 속도 문제를 해결하기 위해 3단계 레이어(규칙, 소형 모델, LLM)를 도입한 사례를 소개합니다. 7B 모델 대신 Go 언어 기반의 결정론적 규칙과 TF-IDF/로지스틱 회귀를 활용하여 추론 속도를 1ms 미만으로 단축했습니다.
핵심 포인트
- LLM은 모든 작업이 아닌 마지막 수단으로만 사용해야 함
- 결정론적 규칙, 소형 모델, LLM 순의 계층적 구조 설계
- TF-IDF와 로지스틱 회귀를 활용한 가벼운 분류기 구축
- GPU 의존도를 낮추고 추론 속도를 획기적으로 개선
요약 (TL;DR): 대부분의 프로덕션 AI 작업은 LLM 작업이 아닙니다. 이메일을 분류하기 위해, 저는 70억 개의 파라미터를 가진 모델을 Go 언어로 작성된 아주 작은 분류기(classifier)로 교체했습니다. 그 규칙은 한 문장으로 요약됩니다. 규칙을 먼저 적용하고, 그다음 작은 모델을 사용하며, LLM은 마지막 수단으로만 사용하십시오. 결과적으로 GPU가 필요 없게 되었고, 1밀리초 미만의 추론 (inference) 속도를 달성했으며, 클라우드 호출은 드물게 발생하게 되었습니다. 실제 수치와 함께 그 방법을 소개합니다.
이 글은 프로덕션 환경에 LLM을 도입하고 그 비용을 직접 지불하고 있는 개발자들을 위한 글입니다. 단순한 데모가 아닙니다.
대부분의 AI 작업은 LLM 작업이 아닙니다
분류 (classify)한다는 것은 짧고 안정적인 목록에서 레이블 (label)을 선택하는 것입니다. 텍스트를 생성 (generate)하는 것은 전혀 다른 문제입니다. 첫 번째 작업에는 작은 모델이 필요합니다. 두 번째 작업은 큰 모델을 쓸 가치가 있습니다. 제가 옹호하는 규칙은 한 문장으로 요약됩니다. LLM을 마지막에 배치하십시오.
설정 (setup)
첫 번째 버전은 모든 이메일을 로컬 LLM에 전달했습니다. GPU에서 Ollama를 통해 서비스되는 70억 개의 파라미터를 가진 모델인 Qwen 2.5 7B를 사용했습니다. Ollama는 자신의 컴퓨터에서 LLM을 실행하는 도구입니다. 작동은 했습니다. 하지만 대가가 컸습니다. GPU를 항상 켜두어야 했고, 관리해야 할 컨테이너가 하나 더 늘었으며, 요구되는 질문에 비해 터무니없이 느렸습니다.
가장 저렴한 것부터 가장 비싼 것까지, 3단계 레이어
모든 이메일은 순서대로 세 가지 레이어를 통과합니다. 답변할 수 있는 첫 번째 레이어에서 멈춥니다.
- 결정론적 규칙 (Deterministic rules). 즉각적이고 정확하며 비용이 들지 않습니다.
- 작은 모델 (A small model). CPU에서 1밀리초 미만의 속도로 작동합니다.
- LLM. 작은 모델이 확신하지 못할 때만 사용합니다.
라우팅 (routing) 코드는 몇 줄이면 충분합니다. 이것이 전체 이야기를 설명해 줍니다.
func (c *Classifier) decide(m Message) Decision {
// 1. 결정론적 규칙: 명백한 발신자, 입구에서 결정됨.
if d := preClassify(m); d != nil {
...
로직은 간단합니다. 각 레이어는 이전 레이어보다 더 많은 비용이 듭니다. 따라서 각 레이어는 이전 레이어들이 결정하지 못한 것만 처리합니다.
규칙이 쉬운 메일을 걸러냅니다
짧은 규칙 목록이 이러한 메일들을 즉시 결정합니다. 발신자 도메인을 확인하고 레이블을 설정합니다. 추측도 없고, 모델 호출도 없으며, 비용도 들지 않습니다. 이러한 이메일은 작은 모델은커녕 LLM에도 도달하지 않습니다.
왜 모델에게 맡기지 않을까요? 정답이 명백할 때는, 읽을 수 있는 규칙이 예측할 수 없는 예측보다 낫기 때문입니다. 규칙은 안정적이고, 테스트 가능하며, 비용이 들지 않습니다. 확실한 모든 것에는 규칙을 유지합니다.
모호한 중간 영역을 위한 작은 모델
그 외의 부분, 즉 명백하지 않은 부분에 대해서는 두 가지 오래된 기술을 사용합니다. TF-IDF와 로지스틱 회귀 (Logistic Regression)입니다.
TF-IDF는 텍스트를 숫자로 변환합니다. 각 단어는 얼마나 흔한지 또는 희귀한지에 따라 가중치를 부여받습니다. 로지스틱 회귀 (Logistic Regression)는 단순한 모델입니다. 이 모델은 해당 숫자들로부터 카테고리를 분리하는 법을 학습합니다. 이 둘이 결합하여 견고하고 가벼운 텍스트 분류기 (Text Classifier)를 만듭니다.
저는 Python의 scikit-learn을 사용하여 6개 카테고리에 걸친 약 5,800개의 레이블이 지정된 이메일로 이를 학습시킵니다. 그런 다음 이를 일반적인 JSON 파일로 내보냅니다. 그 파일의 크기는 2.4 MB입니다. 이를 7B 모델과 비교해 보세요. 수 기가바이트의 용량과 GPU가 필요합니다.
핵심은 추론 (Inference)이 100% Go로 이루어진다는 점입니다. Python도, GPU도, C 의존성도 없습니다. Go 코드는 JSON을 읽고 일반 CPU에서 1밀리초(ms)가 채 안 되는 시간에 예측을 수행합니다. 이 모든 것은 쉘(Shell)과 시스템 도구가 없는 distroless 이미지인 제 운영 환경 이미지 안에 모두 들어갑니다.
정확도는 어떨까요? 5-겹 교차 검증 (5-fold cross-validation)에서 모델은 81%의 정확도에 도달합니다. 교차 검증은 데이터를 5개 부분으로 나눕니다. 4개로 학습하고 나머지 5번째로 테스트하는 과정을 반복합니다. 이는 학습 중에 본 적 없는 메일을 대상으로 측정하는 정직한 지표입니다. 모델은 빈도가 높고 명확한 카테고리에서는 약 0.88로 강력한 성능을 보입니다. 희귀하고 모호한 카테고리에서는 약 0.62로 다소 약합니다.
마지막으로, 모델은 0과 1 사이의 신뢰도 (Confidence)를 반환합니다. 0.60 이상이면 신뢰합니다. 그 미만이면 이메일은 다음 계층으로 넘어갑니다.
81%, 그래서 어쨌다는 건가요?
그 자체만 놓고 보면 81%는 평범해 보입니다. 하지만 계층 구조 (Cascade) 덕분에 이는 문제가 되지 않습니다. 어떤 계층도 완벽할 필요는 없습니다. 각 계층은 단지 자신이 잘하는 일을 수행하기만 하면 됩니다.
규칙은 쉬운 메일을 오류 없이 결정합니다. 작은 모델은 중간 영역의 대부분을 신뢰도와 함께 처리합니다. LLM은 오직 꼬리 부분, 즉 정말로 모호한 메일만을 봅니다. 비용이 많이 드는 호출은 드물게 발생하게 됩니다. 그것이 바로 이 방식의 핵심입니다.
당신은 완벽한 모델을 쫓는 것이 아닙니다. 당신은 비용이 난이도를 따르는 시스템을 쫓는 것입니다. 명확한 이메일은 비용이 들지 않습니다. 어려운 이메일은 단 한 번의 클라우드 호출 비용이 듭니다. 그리고 어려운 이메일은 거의 없습니다.
토큰 일치성 함정 (The token parity trap)
한 가지 까다로운 부분이 있습니다. 모델은 Python에서 학습하지만 Go에서 실행됩니다. 텍스트를 토큰 (token)으로 나누는 방식은 양쪽 모두에서 반드시 동일해야 합니다. 바이트 단위까지 똑같아야 합니다.
토큰은 모델이 계산하는 텍스트 조각으로, 보통 하나의 단어입니다. 만약 Go의 분할 방식이 Python의 분할 방식과 아주 조금이라도 다르다면, 모델은 학습한 적 없는 토큰을 보게 됩니다. 정확도는 소리 없이 떨어집니다. 에러는 발생하지 않지만, 예측 성능만 나빠집니다.
나의 해결책: 두 언어 모두에 정확히 복제된, 직접 구현한 토크나이저 (tokenizer)를 사용하는 것입니다. 동일한 정규 표현식 (regular expression), 악센트를 제거하기 위한 동일한 테이블, 외부 유니코드 (unicode) 라이브러리 미사용. Python과 Go에서 동일한 하나의 명시적인 테이블을 사용합니다.
// 동일한 테이블이 Python 트레이너 (trainer)에 존재합니다.
// 단 하나의 차이만 생겨도 모델은 학습한 적 없는 토큰을 보게 됩니다.
var fold = map[rune]string{'é': "e", 'è': "e", 'ç': "c" /* 전체 테이블 */}
...
일치성 테스트 (parity test)는 실제 텍스트를 사용하여 두 토크나이저를 비교합니다. 만약 두 방식이 어긋나면 빌드 (build)가 실패합니다. 예고 없이 무너지는 정확도보다는 빌드 실패가 낫습니다.
가드레일 (guard-rail)을 가르쳐준 조용한 퇴보
모델은 단순한 루프 (loop)를 통해 개선됩니다. 에이전트 (agent)가 이메일을 잘못된 위치에 분류하면, 제가 그것을 올바른 폴더로 옮깁니다. 그 이동이 새로운 레이블 (label)이 됩니다. 저는 재학습을 진행하고, 모델은 저의 수정을 통해 학습합니다.
어느 날, 이 루프가 저를 공격했습니다. 제가 수동으로 메일을 다시 분류했는데, 한 카테고리의 샘플 수가 학습에 필요한 최소 개수 미만으로 떨어졌습니다. 재학습 과정에서 해당 카테고리는 소리 없이 누락되었습니다. 새 모델은 더 이상 해당 카테고리를 예측할 수 없게 되었습니다. 여전히 에러는 표시되지 않았습니다.
해결책: 이제 학습 스크립트는 제가 의존하는 카테고리를 소리 없이 누락시키는 것을 거부합니다. 스크립트는 중단되며 어떤 폴더의 데이터가 고갈되었는지 알려줍니다.
# 재학습 시 카테고리가 소리 없이 누락되는 것을 방지합니다.
python train.py --in labeled.jsonl --out model.json \
...
이 교훈은 이메일 그 이상을 관통합니다. 조용한 성능 퇴보 (regression)는 시스템 충돌보다 더 위험합니다. 충돌은 눈에 보이지만, 조용히 떨어지는 정확도는 너무 늦게 발견하게 됩니다. 그래서 의도적으로 그 문제를 명확하게 드러나도록 만들어야 합니다.
LLM이 제 자리를 찾는 순간
저는 LLM을 삭제하지 않았습니다. 대신 그 비용을 정당화할 수 있는 곳으로 옮겼습니다. 바로 글쓰기입니다.
이메일을 분류하는 것은 정답이 몇 가지뿐인 폐쇄형 문제 (closed problem)입니다. 하지만 인간의 답장을 작성하는 것은 개방형 문제 (open problem)입니다. 그리고 자유로운 언어 구사는 거대 모델이 그 무엇보다 잘하는 일입니다. 따라서 에이전트가 실제 메시지 초안을 작성해야 할 때는 클라우드 모델 (cloud model)이 이를 처리합니다.
폐쇄형 작업에는 작은 모델을, 개방형 작업에는 큰 모델을 사용하십시오. 각 단계에 적합한 도구를 사용하는 것, 그것이 진짜 교훈이지 "LLM은 나쁘다"가 아닙니다. LLM은 탁월합니다. 단지 모든 것에 적합하지 않을 뿐입니다.
LLM을 사용하기 전 체크리스트
반사적으로 거대 모델을 호출하기 전에, 다음 질문들을 통해 작업을 검토하십시오.
- 작업에 안정적인 정답 세트가 있는가? 그렇다면 그것은 LLM이 아니라 분류 (classification) 문제입니다.
- 명백한 케이스들에 대해 규칙 (rules)을 작성할 수 있는가? 그것부터 먼저 하십시오. 비용이 들지 않습니다.
- 라벨링된 예시 (labelled examples)가 있는가? 그렇다면 작은 모델로도 충분할 것입니다.
- 모델이 자유로운 언어를 이해해야 하는가, 아니면 단순히 라벨을 선택해야 하는가?
- 교차 검증 (cross-validation)을 통해 정직한 정확도를 측정할 수 있는가?
- 작은 모델이 GPU 없이, CPU 상에서, 여러분의 프로덕션 이미지 (production image) 내부에서 실행되는가?
- 토크나이저 (tokenizer)가 학습과 추론 시에 바이트 단위로 완전히 동일한가?
- 가드레일 (guard-rail)이 재학습 시 발생하는 조용한 성능 퇴보를 방지하는가?
- LLM을 그것이 진정으로 더 잘하는 일, 즉 언어 생성 (generating language)을 위해 남겨두었는가?
기억해야 할 점
2026년의 반사적 반응은 모든 것에 거대 모델을 사용하는 것입니다. 하지만 대개 작업에는 그것이 필요하지 않습니다. 계층 구조 (cascade)를 만드는 것이 비용은 훨씬 적게 들고 속도는 훨씬 빠릅니다. 명백한 것에는 규칙을, 중간 단계에는 작은 모델을, 그리고 유일하게 진짜 어려운 작업에는 LLM을 사용하십시오.
이것은 AI를 거부하는 것이 아닙니다. 이것은 엔지니어링 (Engineering)입니다. 비용을 난이도에 맞춰 계층별로 매칭하십시오. AI 시스템을 구축하면서 청구되는 비용이 치솟는 것을 지켜보고 계십니까? 작은 모델이 여러분의 LLM을 대체할 수 있는 곳이 어디인지 알고 싶으십니까? 그것이 바로 제가 하는 일입니다. 저에게 연락주세요. 큰 모델은 그럴 가치가 있는 작업에만 남겨두십시오.
원문은 jrobineau.com에 게시되었습니다.
저는 파리에 기반을 둔 시니어 Go 백엔드 및 DevSecOps 프리랜서 Jules Robineau입니다. 저는 대규모 (2,500만 명 이상의 사용자) 프로덕션 AI/백엔드 시스템을 구축하고 강화합니다. CompTIA PenTest+, TryHackMe 상위 1%. Services · GitHub · LinkedIn
출처: scikit-learn, TfidfVectorizer, scikit-learn, LogisticRegression, scikit-learn, cross-validation
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기