개요
오픈소스 LLM이 빠르게 발전하면서 구글 Gemma, 메타 Llama 3.3, 딥씨크 R1, 알리바바 Qwen 2.5 등 고성능 모델들이 공개되고 있습니다. 그러나 데이터 규제나 보안상 이유로 기업 내부에 프라이빗 AI를 구현해야 하는 기업들은 이런 우수한 오픈소스 모델을 최대한 압축하면서도 필요한 성능을 유지해야 하는 과제에 직면해 있습니다. 이 강의는 **증류 모델(Model Distillation)**과 양자화(Quantization) 두 가지 필수 최적화 기법을 다룹니다. 이 두 기법을 제대로 이해하고 적용하면, 비싼 고급 GPU 없이도 효율적으로 대규모 언어 모델을 활용할 수 있습니다.
배경 / 사전 지식
LLM(Large Language Model, 대규모 언어모델)
매개변수(가중치)가 수십억 개 이상인 신경망 모델을 말합니다. 예: 7B(70억), 32B(320억), 70B(700억), 600B(6000억) 등으로 표기합니다.
매개변수(Parameter, 가중치)
신경망의 가중치를 뜻합니다. 하나의 매개변수를 32비트(4바이트)로 표현하면, 70B 모델은 약 280GB 메모리가 필요합니다(70,000,000,000 × 4 bytes ÷ 1024³ ≈ 280GB).
비트 깊이(Bit Depth)
수치를 표현하는 데 사용하는 비트 수입니다. 32비트(float32, 소수점 포함), 16비트(float16/bfloat16), 8비트(int8), 4비트(int4) 등이 있습니다. 비트 수가 적을수록 메모리는 줄지만 정밀도가 떨어집니다.
VRAM(Video RAM, GPU 메모리)
GPU의 메모리입니다. 게이밍용 RTX 4090은 24GB, 데이터센터용 A100은 40GB 또는 80GB 등 다양합니다. 모델을 로드하고 추론할 때 필요한 메모리입니다.
추론(Inference)
학습이 끝난 모델에 입력을 주고 출력을 얻는 과정입니다. 우리가 LLM을 "사용"할 때가 바로 추론입니다.
핵심 개념
증류 모델(Model Distillation)
원리
큰 "교사 모델(Teacher Model)"이 하는 일을 작은 "학생 모델(Student Model)"이 모방하도록 학습시키는 기법입니다. 이는 마치 어떤 분야의 명인이나 고수가 하는 모든 행동을 후학이 직접 관찰하고 따라하면서 기술을 전수받는 것과 같습니다.
실제 예시
- 교사 모델: Deepseek 670B (또는 다른 고성능 대규모 모델)
- 학생 모델: Alibaba Qwen 7B 또는 Meta Llama 8B 등의 작은 버전
- 학생 모델이 출력하는 값이 교사 모델의 출력과 최대한 가까워지도록 학습됩니다.
특징
-
매개변수 유지: 학생 모델은 기반 모델(Base Model)의 매개변수 개수를 그대로 유지합니다. 예를 들어 Llama 기반 8B 학생 모델은 8B 매개변수를 가집니다. 증류가 모델을 더 작게 만드는 것은 아니고, 이미 작은 기반 모델을 더 좋게 만드는 것입니다.
-
데이터셋 차이: 일반적인 재학습(Fine-tuning)과 달리, 증류는 원래의 훈련 데이터셋을 반드시 사용하지 않습니다. 대신 교사 모델의 동작을 최대한 모방하도록 설계됩니다.
-
상업 모델 불가: OpenAI의 GPT 같은 상업 모델은 내부 가중치나 출력값을 공개하지 않아 교사 모델로 사용하기 어렵습니다. 따라서 Deepseek, Llama, Qwen 등 오픈소스 모델만 교사 모델로 가능합니다.
실무 성능 비교
| 기반 모델 | 크기 옵션 | 한국어 성능 | 특징 | |---------|---------|---------|------| | Qwen | 1.5B, 7B, 14B, 32B | ⭐⭐⭐⭐⭐ 우수 | 아시아 언어(중국어, 한국어) 최적화 | | Llama | 7B, 8B (주로) | ⭐⭐⭐ 중간 | Llama 3.1까지 한국어 미지원, 3.3부터 개선 |
한국어 성능 면에서는 Qwen이 Llama보다 훨씬 우수합니다.
증류의 장점
- 모델 크기 감소는 아니지만, 성능 좋은 기반 모델에서 출발하므로 더 빠르고 효과적입니다.
- 학습 시간 단축 (제로 베이스 학습보다 훨씬 빠른 수렴)
- 일반적인 재학습보다 더 안정적인 결과
양자화(Quantization)
원리
고정밀한 수치값을 더 적은 비트로 근사값으로 변환하는 기술입니다. 원래는 아날로그 신호를 디지털 신호로 변환할 때 사용된 개념이며, LLM에서는 모델의 가중치를 더 낮은 비트 깊이로 표현합니다.
왜 가능한가?
실제 추론 과정에서는 가중치의 매우 정확한 소수점 값이 반드시 필요하지 않습니다. 약간의 오차는 최종 출력 품질에 크게 영향을 주지 않으므로, 저정밀도로도 충분합니다.
주요 비트 깊이 옵션
| 비트 깊이 | VRAM 사용 | 특징 | 활용 | |---------|---------|------|------| | 32비트 | 100% (기준) | 원본 모델, 양자화 없음 | 개발/검증 단계 | | 16비트 | 50% | float16, 많은 프레임워크 지원 | 메모리 여유 있을 때 | | 8비트 | 25% | int8, 정수 표현 | 균형잡힌 성능/메모리 | | 4비트 | 12.5% | int4, 정수만 표현 | 가장 많이 사용 |
4비트 양자화의 특성
- 정수 타입만 표현 가능 (모든 소수점 손실)
- 4비트로 표현할 수 있는 값의 범위가 0~15로 극히 제한됨
- 매우 큰 숫자나 아주 작은 소수값은 모두 손실되지만, 실무에서는 여전히 양호한 결과를 냅니다.
구체적인 메모리 절감 효과
예를 들어 기존 모델이 100GB 비디오 메모리를 필요했다면:
- 4비트 양자화 적용 → 12.5GB만 필요
- 비용: 한 대의 RTX 4090 (24GB)으로 충분
작동 원리
증류 모델의 단계
-
교사 모델 선정
- 고성능이고 오픈소스인 모델 선택 (예: Deepseek 670B)
- 모델의 구조와 가중치가 공개되어 있어야 함
-
학생 모델 선택
- 기존의 성능이 어느 정도 나오는 기반 모델 선택 (예: Llama, Qwen)
- 배포 환경에 맞는 목표 크기(1.5B, 7B, 32B 등) 결정
-
지식 전이 학습(Knowledge Distillation)
- 입력 데이터를 교사 모델과 학생 모델에 모두 제공
- 두 모델의 출력값(또는 중간 활성화)의 차이를 최소화하도록 손실함수 설정
- 손실함수: 일반적으로 KL Divergence 또는 MSE 사용
- 학생 모델의 가중치를 업데이트하면서 교사 모델의 행동을 따라가도록 학습
-
평가 및 최적화
- 학생 모델의 성능이 목표 수준에 도달했는지 검증
- 필요시 하이퍼파라미터 조정 후 재학습
양자화의 단계
-
모델 선택 및 비트 깊이 결정
- 배포 환경과 성능 요구사항에 따라 4비트, 8비트, 16비트 중 선택
- 엣지 기기(CPU) → 4비트 GGUF 권장
- 클라우드 서빙(GPU) → 4비트 AWQ 권장
-
양자화 기법 선택
- GGUF (CPU/GPU/에지 기기 모두 지원, 범용적)
- AWQ (GPU 최적화, 배치 처리 시 고성능)
- GPTQ (다른 4비트 양자화 기법)
-
변환 수행
- 모델의 가중치를 선택한 비트 깊이로 변환
- 스케일 팩터 등을 함께 저장하여 추론 시 원래 값으로 복원 가능하도록 함
- 변환 과정은 자동화 도구(ollama, llama.cpp 등)로 수행 가능
-
성능 검증
- 양자화 전후 출력값 비교
- 한국어 등 특정 언어나 도메인 성능 확인
- 지연시간, 처리량 측정
메모리 계산 실전 예시
32B 모델
- 양자화 없음 (32비트): 32 × 4 바이트 = 128GB → RTX 4090 5~6장 필요
- 4비트 양자화: 128GB ÷ 8 = 16GB → RTX 4090 1장으로 충분
70B 모델
- 양자화 없음 (32비트): 70 × 4 바이트 = 280GB → RTX 4090 12장 필요
- 8비트 양자화: 70GB → RTX 4090 3장
- 4비트 양자화: 35GB → RTX 4090 2장
참고: RTX 4090 한 장 가격이 약 600만원이므로, 32B 모델만 배포해도 5,000만원 이상의 하드웨어 비용이 발생합니다.
간편 계산법
8비트 기준으로 계산한 후, 4비트로 내려가면 약 절반 수준이 된다고 생각하면 됩니다.
- 32B → 대략 32GB (8비트) → 16GB (4비트)
- 70B → 대략 70GB (8비트) → 35GB (4비트)
코드 예시
예시 1: GGUF 양자화 모델 로드 및 추론 (CPU/GPU 혼합 가능)
# llama-cpp-python 라이브러리 사용
# 설치: pip install llama-cpp-python
from llama_cpp import Llama
# 4비트 GGUF 형식의 양자화된 모델 로드
model = Llama(
model_path="./qwen-7b-q4_k_m.gguf", # 4비트 양자화 Qwen 7B
n_gpu_layers=-1, # -1: GPU의 모든 계층 사용 (가능한 많이)
n_ctx=2048, # 컨텍스트 길이 (얼마나 긴 대화 가능)
n_threads=8, # CPU 스레드 수 (CPU 병렬 처리)
)
# 간단한 추론
prompt = "안녕하세요, 당신은"
output = model(prompt, max_tokens=100)
print(output['choices'][0]['text'])
설명:
model_path: GGUF 형식의 양자화된 모델 파일 경로n_gpu_layers=-1: 모든 계층을 GPU에서 처리. 만약 GPU 메모리 부족하면 일부 계층을 CPU에서도 처리 가능- 4비트 양자화로 인해 매우 작은 VRAM으로도 실행 가능
- CPU와 GPU를 자동으로 혼합하여 사용 가능 (엣지 디바이스에서도 동작)
예시 2: AWQ 양자화 모델 로드 (GPU 배치 처리 최적화)
# AutoAWQ 라이브러리 사용
# 설치: pip install autoawq
from awq import AutoAWQForCausalLM
from transformers import AutoTokenizer
# AWQ 양자화된 모델 로드 (GPU 최적화)
model_name = "models/Qwen-7B-AWQ"
model = AutoAWQForCausalLM.from_pretrained(
model_name,
device_map="auto", # 자동 GPU 할당
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 텍스트 생성 (배치 처리에 최적)
prompt = "안녕하세요, 당신은"
inputs = tokenizer(prompt, return_tensors="pt")
# GPU에서 추론 (배치 처리 시 고처리량)
outputs = model.generate(
**inputs,
max_length=100,
do_sample=True,
temperature=0.7,
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)
설명:
- AWQ는 GPU 연산을 최적화하여, 여러 사용자의 요청을 동시에 처리(배치 처리)할 때 처리량이 높습니다.
- 프로덕션 환경에서 여러 사용자의 동시 요청을 처리해야 할 때 AWQ 권장
예시 3: 메모리 사용량 계산 함수
def estimate_model_memory_gb(param_billion, quantization_bits=32):
"""
LLM 모델의 대략적 메모리 요구량을 계산합니다.
Args:
param_billion: 매개변수 수 (단위: 십억, 예: 7은 7B 모델)
quantization_bits: 양자화 비트 깊이 (32, 16, 8, 4)
Returns:
필요 VRAM (GB 단위)
"""
bytes_per_param = quantization_bits / 8
total_bytes = param_billion * 1_000_000_000 * bytes_per_param
memory_gb = total_bytes / (1024 ** 3)
return memory_gb
# 다양한 모델과 양자화 수준 비교
models = [
("Qwen-7B", 7),
("Qwen-32B", 32),
("Llama-70B", 70),
]
print("모델별 메모리 요구량:\n")
for model_name, param_size in models:
print(f"{model_name}:")
for bits in [32, 16, 8, 4]:
mem = estimate_model_memory_gb(param_size, bits)
gpu_count = (mem + 23.9) // 24 # RTX 4090 기준 (24GB)
print(f" {bits}비트: {mem:6.1f} GB (4090 약 {int(gpu_count)}장)")
print()
출력 예:
Qwen-7B:
32비트: 28.0 GB (4090 약 2장)
16비트: 14.0 GB (4090 약 1장)
8비트: 7.0 GB (4090 약 1장)
4비트: 3.5 GB (4090 약 1장)
Qwen-32B:
32비트: 128.0 GB (4090 약 6장)
16비트: 64.0 GB (4090 약 3장)
8비트: 32.0 GB (4090 약 2장)
4비트: 16.0 GB (4090 약 1장)
Llama-70B:
32비트: 280.0 GB (4090 약 12장)
16비트: 140.0 GB (4090 약 6장)
8비트: 70.0 GB (4090 약 3장)
4비트: 35.0 GB (4090 약 2장)
함정·실수
1. 양자화 후 성능 급락 가정
실수: "4비트 양자화는 성능이 많이 떨어질 것"이라고 가정하고 포기하기.
현실: 많은 실무 환경에서 4비트 양자화해도 충분히 좋은 결과를 냅니다. 최근 트렌드는 더 극단적인 양자화(1.5비트까지)를 시도하는 중입니다.
회피법: 실제로 테스트하세요. 당신의 구체적인 유즈 케이스에서 양자화 모델이 얼마나 성능이 저하되는지 직접 측정하는 것이 가장 중요합니다. 예상과 현실이 다를 수 있습니다.
2. 한국어 성능 저하
실수: Llama 기반 증류 모델을 한국어 사용 용도로 선택하기.
원인: Llama 3.1까지는 공식적으로 한국어를 지원하지 않았기 때문에, 한국어 입력이 들어오면 중국어로 변환되거나 불안정한 출력이 발생합니다. Llama 3.3부터 개선되었으나, 여전히 Qwen이 우수합니다.
회피법:
- 한국어가 필요한 경우 Qwen 기반 모델 사용
- 또는 영어 중심으로 시스템 설계: 한국어 입력 → 영어로 번역 → 추론 → 결과를 한국어로 역번역
- 이 방식이 직접 한국어로 추론하는 것보다 품질이 더 좋을 수 있습니다.
3. 모델 버전에 과도하게 의존
실수: 특정 모델 버전에 아키텍처를 과도하게 의존하는 구축.
문제: LLM 기술이 3개월마다 급격히 발전하므로, "이 버전으로 최종 결정"하면 6개월 후 훨씬 좋은 모델이 나왔을 때 대응이 어렵습니다.
회피법:
- 추론 엔진으로 표준화된 포맷 사용 (GGUF 등)
- 모델 파일만 교체할 수 있는 느슨한 결합 아키텍처 설계
- API 엔드포인트를 추상화하여 백엔드 모델 변경이 앱 코드에 영향을 주지 않도록 구성
4. 증류와 양자화의 순서 혼동
실수: "증류만 하거나 양자화만 하면 충분하다"고 생각하기.
현실: 두 기법은 서로 다른 문제를 해결합니다.
- 증류: 모델 크기 감소 (70B → 32B → 7B, 더 좋은 기반에서 출발)
- 양자화: 비트 깊이 감소 (32비트 → 4비트, 메모리 절감)
회피법: 일반적으로 증류 + 양자화를 함께 적용하여 크기와 메모리를 동시에 최적화합니다. 이것이 가장 실용적입니다.
5. 배포 환경과 맞지 않는 기법 선택
실수: 엣지 디바이스(스마트폰, IoT)에 AWQ 형식만 사용하려고 하기.
문제: AWQ는 GPU 활용도를 높이지만, CPU 기반의 엣지 디바이스에서는 비효율적입니다.
회피법:
- CPU 기반 엣지 디바이스 → GGUF 선택
- 클라우드 서빙 (다중 사용자, 배치 처리) → AWQ 선택
- 혼합 환경이면 GGUF로 통일하되, 클라우드에서는 AWQ로도 병렬 제공
6. 테스트 부족
실수: 개발 환경에서만 성능 확인하고, 실제 프로덕션 워크로드로 테스트하지 않기.
문제: 특정 도메인(금융 보고서, 의료 기록) 또는 특수 형식의 입력에서 성능이 급락할 수 있습니다.
회피법:
- 실제 사용 사례 데이터로 A/B 테스트 실행
- 한국어 포함 다국어 성능 평가
- 정확도, 응답시간, 메모리 사용량을 모두 측정
베스트 프랙티스
1. 증류와 양자화의 균형
권장 방법:
- 일반적인 용도: 증류 + 4비트 양자화 조합
- 높은 품질 필요: 증류 + 8비트 양자화
- 극한 최적화: 증류 + 1.5비트 양자화 (품질 손실 큼)
판단 기준:
- GPU 여유 있음 → 8비트 이상 사용
- GPU 부족 → 4비트 사용하되, 실제 테스트로 품질 확인
- 엣지 디바이스 → GGUF + 4비트
2. 기반 모델 선택 기준
한국어 포함 사용 사례:
- ✅ Qwen (1.5B ~ 32B) — 가장 권장
- ⚠️ Llama 3.3 이상 — 개선되었으나 Qwen이 더 우수
- ❌ Llama 3.1 이하 — 한국어 미지원
영어 중심 사용 사례:
- Llama — 성능과 생태계 우수
- Mistral — 컴팩트함
- Deepseek — 고성능 (교사 모델로 좋음)
3. 아키텍처 설계: 모델 교체 가능성 고려
┌─────────────────────────────────┐
│ 응용 프로그램 (REST API) │
└────────────┬────────────────────┘
│ (표준화된 인터페이스)
┌─────▼──────┐
│ 추론 엔진 │
│ (vLLM 등) │ (GGUF/표준 포맷 지원)
└─────┬──────┘
│
┌────────▼────────┐
│ 모델 파일 저장소 │
│ (모델만 교체, │
│ 엔드포인트 동일)
└─────────────────┘
- 추론 엔진과 응용 프로그램 간 인터페이스 추상화
- 모델 파일만 업데이트해도 앱 코드 수정 없음
- 예: vLLM, Text Generation WebUI, llama.cpp 등 표준 엔진 사용
4. 성능 측정 체크리스트
[ ] 추론 속도 (tokens/sec)
[ ] 메모리 사용량 (VRAM, RAM)
[ ] 정확도/품질 (자동 평가 + 수동 검증)
[ ] 한국어/다국어 성능
[ ] 지연시간 (latency, ms)
[ ] 동시 사용자 수 처리 능력 (처리량)
[ ] 비용 (GPU 비용 × 필요 시간)
5. 프로덕션 배포 단계
단계별 진행:
- 개발 단계: 양자화 없는 풀 모델로 기능 검증
- 최적화 단계: 4비트 양자화 모델로 메모리 절감 확인
- 스트레스 테스트: 실제 워크로드 + 동시 사용자로 성능 검증
- 롤아웃: 카나리 배포(일부 사용자)로 시작 → 전체 롤아웃
모니터링:
- 모델 응답 품질 실시간 모니터링
- GPU 메모리 사용률 추적
- 사용자 피드백 수집 (품질 저하 감지)
6. 더 나아가는 기술
프루닝(Pruning): 불필요한 뉴런/가중치 제거
로라(LoRA): 특정 도메인에 맞춘 가벼운 미세조정
스펙 감소(Speculative Decoding): 작은 모델로 먼저 추론 후 큰 모델로 검증
모델 병합: 여러 특화 모델을 하나의 모델로 통합
이들은 단독 또는 증류/양자화와 조합하여 사용 가능합니다.
7. 영어 우선 전략
증류·양자화 모델은 한국어 성능이 떨어질 수 있으므로, 가능하면:
- 사용자 입력을 한국어 → 영어로 번역
- 영어로 추론 실행
- 결과를 영어 → 한국어로 역번역
이 방식이 직접 한국어로 추론하는 것보다 품질이 더 좋을 수 있습니다.
참고
영상 내 언급 자료:
- 드림플로우 추가 영상: https://bit.ly/4hFgZmC
- 토크아이티 웨비나 참여/자료 다운로드: https://talkit.tv
- 문의 이메일: ask@talkit.tv
- 마케팅 문의: talkit@talkit.tv, 02-565-0012
주요 오픈소스 모델:
- Deepseek: 고성능 교사 모델로 자주 사용
- Alibaba Qwen: 한국어·중국어 성능 우수
- Meta Llama: 영어 성능 우수, 3.3부터 다국어 개선
- Google Gemma: 경량 모델 옵션
양자화 도구 및 포맷:
- GGUF: llama.cpp 등 범용, CPU/GPU 호환
- AWQ: GPU 최적화, 배치 처리
- GPTQ: 다른 4비트 양자화 기법
- BitsAndBytes: Hugging Face 생태계
추론 엔진:
- vLLM: 고성능 추론, 배치 처리 최적화
- Text Generation WebUI: 사용자 친화적 로컬 실행
- llama.cpp: CPU 친화적, 가벼움
- Ollama: 사용 용이한 로컬 실행
학습 리소스 (영상 내 미제시):
- Hugging Face Model Hub: 양자화된 모델 다운로드
- Papers with Code: 최신 양자화/증류 논문
- GitHub (TheBloke 등): 양자화된 모델 제공자