70B 모델을 처음부터 파인튜닝하면 H100 4~8개, 수십만 달러가 필요해요.
LoRA/QLoRA를 쓰면 RTX 4090 한 장으로, 몇 시간 안에, $10 정도 비용으로 동일한 작업이 가능해요.
왜 풀 파인튜닝 대신 LoRA인가
LLM을 풀 파인튜닝하면 수십억 개의 파라미터를 전부 업데이트해요. 메모리와 연산이 엄청나게 필요하죠.
LoRA의 핵심 아이디어는 이래요.
"모델을 업데이트할 때 변화량 자체가 저랭크(low-rank)다."
즉, 수십억 개 파라미터를 다 바꾸는 게 아니라 변화량을 표현하는 작은 행렬 2개만 학습해요.
풀 파인튜닝:
W (d×d 행렬 전체) 업데이트 → 수백만 GB
LoRA:
W' = W + BA
A: (r×d), B: (d×r) — r은 보통 8~64
→ 학습 파라미터가 0.1~1%로 줄어듦
기존 가중치 W는 고정(freeze), A와 B 어댑터만 학습해요. 추론 때는 W+BA를 합쳐서 레이턴시 오버헤드 없이 사용해요.
QLoRA — 메모리를 더 줄이는 법
LoRA만으로도 파라미터는 줄었지만, 기반 모델 자체가 FP16으로 메모리를 먹어요. 7B 모델 기준 14GB.
QLoRA는 여기에 4비트 양자화를 추가해요.
LoRA: 기반 모델 FP16 (14GB) + 어댑터 → RTX 4090 필요
QLoRA: 기반 모델 NF4 4비트 (4GB) + 어댑터 FP16 → RTX 3090으로 가능
QLoRA 3가지 핵심 기술
- NF4 양자화 — 신경망 가중치 분포(정규분포)에 최적화된 4비트 포맷
- 이중 양자화 — 양자화 상수 자체도 양자화 → 추가 메모리 절감
- 페이지드 옵티마이저 — 메모리 스파이크 시 CPU 메모리로 임시 오프로드
품질은 어느 정도 잃을까? LoRA 대비 1~2% 손실, 풀 파인튜닝 대비 5~10% 손실이에요. 대부분의 프로덕션 팀이 이 트레이드오프를 받아들여요.
GPU 요구사항 정리
모델 크기 LoRA QLoRA
| 7~8B | RTX 4090 (24GB) | RTX 3090 (24GB) 또는 RTX 4080 (16GB) |
| 13B | A100 40GB | RTX 4090 (24GB) |
| 70B | 2~4× H100 | A100 80GB 1개 |
핵심 하이퍼파라미터
Rank (r)
어댑터의 표현력을 결정해요. 높을수록 품질 좋지만 메모리 증가.
스타일/포맷 변경: r=8~16
도메인 적응: r=16~32
추론 능력 이전: r=32~64
Alpha (α)
어댑터의 학습률 스케일링 팩터예요. 보통 α = 2×r로 시작해요.
r=16이면 α=32 (실효 학습률 = α/r = 2.0)
Target Modules
어떤 레이어에 LoRA를 붙일지 결정해요.
# 기본 (어텐션만)
target_modules=["q_proj", "v_proj"]
# 권장 (어텐션 + MLP)
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"]
# 간단하게
target_modules="all-linear" # 모든 선형 레이어
실전 코드 — Unsloth + SFTTrainer (2026 권장 스택)
Unsloth는 기존 HuggingFace PEFT 대비 메모리 40% 절감, 속도 2배 향상이에요. 2026년 현재 가장 많이 쓰는 QLoRA 스택이에요.
from unsloth import FastLanguageModel
from trl import SFTTrainer
from transformers import TrainingArguments
# 1. 모델 로드 (QLoRA)
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="meta-llama/Llama-3.1-8B-Instruct",
max_seq_length=2048,
load_in_4bit=True, # QLoRA 활성화
)
# 2. LoRA 어댑터 추가
model = FastLanguageModel.get_peft_model(
model,
r=16,
lora_alpha=32,
target_modules="all-linear",
lora_dropout=0.05,
use_dora=True, # DoRA: 품질 개선 (2026 권장)
)
# 3. 학습
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset,
args=TrainingArguments(
output_dir="./output",
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
num_train_epochs=3,
learning_rate=2e-4,
lr_scheduler_type="cosine",
bf16=True,
logging_steps=10,
save_strategy="epoch",
),
)
trainer.train()
# 4. 어댑터 저장
model.save_pretrained("my-lora-adapter")
데이터셋 형식
파인튜닝 데이터는 대화 형식으로 준비해요.
# 데이터 형식 (JSON Lines)
{"messages": [
{"role": "user", "content": "환불 정책이 어떻게 되나요?"},
{"role": "assistant", "content": "구매 후 30일 이내 환불 가능합니다."}
]}
# 최소 데이터량 가이드
스타일/포맷: 200~1,000개
태스크 특화: 1,000~5,000개
도메인 지식: 10,000~50,000개
어댑터 병합 후 배포
학습이 끝나면 어댑터를 기반 모델에 합쳐서 배포해요.
# 어댑터 + 기반 모델 병합
merged_model = model.merge_and_unload()
merged_model.save_pretrained("merged-model")
# GGUF로 변환 (Ollama/llama.cpp용)
model.save_pretrained_gguf("my-model-gguf", tokenizer, quantization_method="q4_k_m")
병합 후 어댑터 파일 크기는 50~200MB예요. 기반 모델(14GB)과 별도로 버전 관리 가능해요.
vLLM으로 멀티 LoRA 서빙
하나의 기반 모델 위에 여러 LoRA 어댑터를 동시에 서빙해요. 고객마다 다른 어댑터를 쓸 수 있어요.
from vllm import LLM, LoRARequest
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
enable_lora=True,
max_lora_rank=64
)
# 요청마다 다른 어댑터 선택
output = llm.generate(
"고객 문의 처리해줘",
lora_request=LoRARequest("customer_support", 1, "./adapters/cs_lora")
)
LoRA 변종들
DoRA (Direction + Rank Adaptation) 가중치를 크기(magnitude)와 방향(direction)으로 분리해서 학습해요. 2026년 현재 LoRA 대신 기본 선택으로 자리잡고 있어요. use_dora=True 한 줄만 추가하면 돼요.
LoftQ / PiSSA QLoRA에서 4비트 양자화 오류를 더 잘 보정하는 초기화 방법이에요. 양자화 품질 저하가 눈에 띌 때 시도해봐요.
LongLoRA 긴 컨텍스트(32K, 128K)로 파인튜닝할 때 사용해요. Shifted Short Attention으로 메모리 효율을 높여요.
파인튜닝 vs RAG vs 프롬프트 엔지니어링
언제 파인튜닝을 써야 하는지 명확히 해야 해요.
프롬프트 엔지니어링:
→ 빠른 실험, 지식이 자주 바뀜
RAG:
→ 최신 지식 필요, 출처 추적 중요
파인튜닝 (LoRA/QLoRA):
→ 일관된 출력 형식 필요
→ 특정 도메인 어조/스타일 학습
→ 고빈도 요청에서 토큰 비용 절감
→ 프라이버시 (데이터를 외부 API에 안 보내고 싶음)
2026년 현재 가장 좋은 전략은 RAG(사실 정보) + LoRA(행동 양식) 조합이에요.
마무리
LoRA/QLoRA를 한 줄로 요약하면 이래요.
"기반 모델은 건드리지 말고, 변화량만 작게 학습해라."
7B 모델 기준 RTX 4090 한 장에서 몇 시간 만에 파인튜닝이 가능해요. 어댑터는 50~200MB로 작아서 버전 관리도 편해요. 2026년에는 DoRA + QLoRA 조합이 가장 많이 쓰이는 스택이에요. 😄
'LLM' 카테고리의 다른 글
| KV Cache 완전 정리 — PagedAttention vs RadixAttention, SGLang이 빠른 이유 (1) | 2026.04.09 |
|---|---|
| LLM 지식 증류(Knowledge Distillation) 완전 정리 — 큰 모델의 지식을 작은 모델에 이식하는 법 (0) | 2026.04.09 |
| LLM 양자화 완전 정리 — FP8, AWQ, GPTQ, GGUF 차이와 선택법 (1) | 2026.04.09 |
| SGLang PD 분리 배포 완전 가이드 — Prefill/Decode 분리로 처리량 5배 올리기 (0) | 2026.04.09 |
| SGLang launch_server 파라미터 완전 정리 (0) | 2026.04.09 |