RSS

로컬 LLM 모델 고르기: 파라미터, 양자화, MoE를 실측으로 비교

온프레미스 추론 서버에 모델이 25개, 154GB 쌓여 있었습니다. 저는 필요할 때마다 하나씩 받았고, 어느 시점부터 무엇을 왜 갖고 있는지 설명할 수 없게 됐습니다.

정리하면서 두 번 실험했는데 한 번은 제 예상이 맞았고 한 번은 완전히 빗나갔습니다. 그 과정에서 모델을 고를 때 실제로 봐야 하는 것이 무엇인지 정리됐습니다.

먼저 알아야 할 네 가지

모델 목록을 보면 이런 값들이 붙어 있습니다.

qwen3.6:35b-a3b    36.0B    Q4_K_M    vision, completion, tools, thinking
exaone3.5:2.4b      2.7B    Q4_K_M    completion
bge-m3:latest     566.7M    F16       embedding

파라미터 수 (2.4B, 27B, 35B)

모델의 크기입니다. 클수록 대체로 똑똑하지만 느려지고 메모리를 더 씁니다. 뒤에서 보겠지만 이 "대체로"가 항상 성립하지는 않습니다.

양자화 (Q4_K_M, Q8_0, F16)

가중치를 몇 비트로 눌러 담았는지입니다. F16이 원본에 가깝고 Q8_0, Q4_K_M 순으로 작아집니다. Q4_K_M은 4비트 정도로 눌러 크기를 3분의 1 이하로 줄이면서 품질 손실은 크지 않은 지점이라 가장 널리 쓰입니다.

같은 27B라도 F16이면 50GB가 넘고 Q4_K_M이면 17GB입니다. 메모리가 빠듯하면 모델을 줄이기 전에 양자화를 먼저 낮추는 것이 보통 낫습니다.

기능 (capabilities)

이게 실무에서 제일 자주 발목을 잡습니다.

없으면
completion 일반 텍스트 생성 대화 자체가 안 됨
tools 함수 호출 도구를 부르는 에이전트 작업 불가
vision 이미지 입력 스크린샷·문서 이미지 처리 불가
thinking 추론 단계 분리 복잡한 추론에서 불리
embedding 벡터 변환 전용 대화에는 아예 못 씀

저도 정리하다가 completion만 있는 모델을 구조화 출력이 필요한 자리에 물려둔 걸 발견했습니다. 목록에서는 멀쩡해 보이는데 실제로 호출하면 실패합니다.

임베딩 모델은 성격이 다릅니다

임베딩 모델은 문장을 벡터로 바꾸는 전용 모델이고, 한 번 정하면 바꾸기 어렵습니다. 모델마다 벡터 차원이 달라서, 바꾸면 이미 저장한 벡터를 전부 다시 만들어야 합니다. 문서가 수천 건이면 몇 시간짜리 작업입니다.

저희 설정 화면에도 이 한 줄이 박혀 있습니다.

임베딩 모델은 기존 벡터 차원과 일치해야 하므로 이 화면에서 변경하지 않습니다.

이 서버가 특이한 점

일반적인 GPU 서버는 전용 VRAM에 모델을 올립니다. 이 서버는 내장 GPU라 전용 VRAM이 없고 시스템 메모리를 나눠 씁니다. 통합 메모리 59GB가 그대로 모델 용량 한도입니다.

이 구조에서는 병목이 연산이 아니라 메모리 대역폭입니다. 매 토큰마다 모델 가중치를 메모리에서 읽어와야 하는데, 그 읽기 속도가 천장이 됩니다. 모델이 크면 읽을 게 많아서 느립니다. 단순합니다.

이 사실이 뒤의 두 실험 결과를 전부 설명합니다.

실험 1 — 한국어 모델을 키웠더니 나빠졌습니다

한국어 특화 소형 모델(2.4B)을 쓰고 있었는데, 같은 계열의 7.8B가 있길래 받아봤습니다. 저는 같은 계열의 더 큰 모델이니 안전한 업그레이드라고 생각했습니다. 재보지도 않고 그렇게 단정했습니다.

같은 질문 세 개를 던져 비교했습니다.

curl -s -X POST http://<추론서>/api/generate \
  -H 'Content-Type: application/json' \
  -d '{"model":"...","prompt":"...","stream":false,
       "options":{"temperature":0.2,"num_predict":400}}'

응답에 eval_count(생성 토큰 수)와 eval_duration(나노초)이 들어 있어서 초당 토큰을 계산할 수 있습니다.

속도 문서 요약 한국어 교정
2.4B 47 tok/s 원문을 뭉갬 좋음
7.8B 18 tok/s 정확 좋음

2.6배 느려졌는데 이긴 항목은 하나였습니다. 그리고 첫 테스트에서 7.8B가 존재하지 않는 제품 이름을 하나 지어냈습니다. 회계 소프트웨어를 재고 관리 도구인 것처럼 추천했습니다.

더 결정적인 것은, 이미 갖고 있던 범용 9B 모델이 비슷한 속도에 더 나은 답을 냈다는 점입니다. toolsvision까지 되는데도요.

7.8B는 지웠습니다. 크기를 키우면 나아진다는 가정이 틀렸습니다.

실험 2 — 더 큰 모델이 6배 빨랐습니다

두 번째는 반대였습니다.

쓰던 모델은 27B였는데, 같은 세대에 35B-A3B라는 태그가 있었습니다. 이건 MoE(Mixture of Experts) 모델입니다.

MoE가 무엇인가

일반 모델(dense)은 토큰 하나를 만들 때 모든 가중치를 다 읽습니다. 27B면 27B 전부입니다.

MoE는 가중치를 여러 "전문가"로 나눠두고 매 토큰마다 그중 일부만 씁니다. 35b-a3b는 총 35B인데 활성은 3B라는 뜻입니다.

메모리에는 35B 전체를 올려둬야 하니 용량은 더 먹습니다. 대신 매번 읽는 양이 3B뿐이라 대역폭 부담이 훨씬 적습니다.

이 서버처럼 대역폭이 병목인 환경에서는 이게 정확히 유리합니다.

결과

파라미터 디스크 속도 상담 답변 생성
27B (dense) 27.8B 17.4GB 4.3~4.8 tok/s 113.8초
35B-A3B (MoE) 36.0B 23.9GB 23.5~27.7 tok/s 17.8초

총 파라미터가 더 큰 쪽이 6배 빨랐습니다.

품질도 MoE가 나았습니다. 요약에서 존댓말을 지켰고, 상담 답변은 "엑셀 구조 분석 → 데이터 표준화 → 시범 도입"으로 구체적이었습니다. 27B는 "복잡한 커스터마이징보다 표준 기능"이라는 일반론에 머물렀습니다.

27B의 4.3 tok/s는 사실 실용 속도가 아닙니다. 100토큰 답변에 2분이 걸리니 사람이 기다릴 수 없습니다.

정리하면서 지운 것들

25개 중 17개를 지웠습니다. 기준은 이랬습니다.

같은 자리에 더 나은 게 있으면 지웁니다. 구세대 14B는 신세대 9B보다 느리고 못했습니다.

전용 모델은 범용이 그 기능을 흡수했으면 지웁니다. vision 전용 모델 두 개를 갖고 있었는데, 주력 모델 라인업이 전부 vision을 지원하고 있었습니다.

참조가 없으면 지웁니다. 코드베이스 전체를 훑어 모델 이름을 찾았고, 32B 코딩 모델은 어디서도 부르지 않았습니다. 20GB짜리였습니다.

임베딩은 하나만 남깁니다. 영어권 임베딩 모델이 네 개 있었는데 설정은 다국어 모델 하나를 가리키고 있었습니다.

한 가지 함정이 있었습니다. 코드에서 지우려던 모델 이름이 검색됐는데, 열어보니 주석데모 시드 데이터였습니다. 실제 사용이 아니었습니다. 문자열 검색만으로 판단하면 안 됩니다.

결과는 25개 154GB → 8개 54GB입니다.

남는 이야기

크기는 품질의 대리 지표일 뿐입니다. 같은 계열에서 키웠더니 나빠졌고, 다른 구조로 키웠더니 6배 빨라졌습니다. 두 결과 모두 재보기 전에는 알 수 없었습니다.

하드웨어 구조를 알아야 모델을 고를 수 있습니다. 전용 VRAM이 넉넉한 서버라면 27B dense가 충분히 빨랐을 겁니다. 대역폭이 병목인 환경이라서 MoE가 이겼습니다. 같은 모델이 장비에 따라 정반대 평가를 받습니다.

목록에 있는 것과 쓰는 것은 다릅니다. 154GB 중 실제로 설정이 가리키던 것은 네 개뿐이었습니다. 나머지는 "언젠가 써볼까 봐" 받아둔 것들이었고, 그중 상당수는 이미 상위 호환이 나와 있었습니다.

측정은 어렵지 않습니다. API 응답에 토큰 수와 소요 시간이 들어 있어서, 같은 질문을 몇 개 던지고 초당 토큰을 비교하면 30분이면 끝납니다. 제가 두 번 다 틀린 가정을 갖고 있었던 이유는 그 30분을 쓰지 않았기 때문입니다.