logo
aillmfinetuninglora

LoRA와 QLoRA - 적은 자원으로 LLM 파인튜닝하기

LLM을 우리 도메인에 맞게 길들이고 싶을 때 가장 먼저 떠오르는 건 파인튜닝입니다. 그런데 수십억 개 파라미터를 통째로 다시 학습하려면 GPU가 몇 장씩 필요합니다. 이 부담을 확 낮춘 기법이 LoRA이고, 거기서 메모리를 한 번 더 줄인 것이 QLoRA입니다.

이 글에서는 두 기법이 왜 나왔고, 원리가 무엇이며, 실무에서 언제 쓰는지를 정리합니다.


1. 풀 파인튜닝의 부담부터 보기

풀 파인튜닝(full fine-tuning)은 모델의 모든 가중치를 다시 학습합니다. 이게 왜 무거운지 감을 잡아봅시다.

70억(7B) 파라미터 모델을 예로 들면, 학습에 필요한 메모리는 파라미터 자체만이 아닙니다.

항목대략 필요량(7B 기준)설명
모델 가중치~14GBfp16 기준 파라미터당 2바이트
그래디언트~14GB가중치와 같은 크기
옵티마이저 상태~28GBAdam은 파라미터당 상태 2개

합치면 7B 모델 하나 학습에 50GB 이상이 듭니다. 여기에 활성값(activation)까지 더하면 소비자용 GPU 한 장으론 어림도 없습니다. 게다가 학습 결과물은 원본과 똑같은 크기의 새 모델 파일이 통째로 나옵니다. 도메인별로 여러 개 만들면 저장·배포 비용도 부담입니다.

핵심 문제: "성능은 원하지만, 모든 파라미터를 건드리는 건 너무 비싸다."


2. LoRA - 저랭크 어댑터라는 아이디어

LoRA(Low-Rank Adaptation) 의 발상은 단순합니다.

"원본 가중치는 얼어붙게(freeze) 두고, 그 옆에 작은 행렬 두 개만 새로 학습하자."

2-1. 저랭크 분해

파인튜닝이란 결국 원본 가중치 W에 변화량 ΔW를 더하는 일입니다.

새 가중치 = W(원본, 동결) + ΔW(학습으로 얻는 변화량)

LoRA는 이 ΔW를 통째로 학습하는 대신, 두 개의 작은 행렬 곱으로 근사합니다.

ΔW ≈ B × A - W : (d × d) 큰 행렬 → 동결(학습 안 함) - A : (r × d) 작은 행렬 → 학습 - B : (d × r) 작은 행렬 → 학습 - r : 랭크(rank), 보통 8 / 16 / 32 처럼 아주 작음

여기서 r랭크입니다. d가 4096이고 r이 8이라면, 원래 4096 × 4096 ≈ 1,600만 개를 학습할 것을 2 × (8 × 4096) ≈ 6.5만 개만 학습합니다. 학습 파라미터가 수백 분의 1로 줄어듭니다.

2-2. 왜 이게 통할까

"변화량을 저랭크로 근사해도 되나?" 하는 의문이 생깁니다. LoRA 논문의 관찰은, 파인튜닝으로 생기는 가중치 변화가 실제로는 낮은 랭크 구조를 가진다는 것입니다. 즉 큰 행렬을 다 흔들 필요 없이, 몇 개의 방향만 조정해도 도메인 적응이 된다는 뜻입니다.

# 개념 코드: 선형 계층에 LoRA를 얹는 모습 class LoRALinear: def __init__(self, base_linear, r=8, alpha=16): self.base = base_linear # 원본, 동결 self.base.weight.requires_grad = False d_out, d_in = base_linear.weight.shape self.A = zeros(r, d_in, requires_grad=True) # 학습 self.B = zeros(d_out, r, requires_grad=True) # 학습 self.scale = alpha / r def forward(self, x): # 원본 출력 + 저랭크 보정 return self.base(x) + (x @ self.A.T @ self.B.T) * self.scale

alpha는 보정량의 스케일을 조절하는 하이퍼파라미터입니다. 보통 alpha / r 비율로 영향력을 맞춥니다.


3. 학습 후 메모리가 줄어드는 이유

LoRA가 메모리를 아끼는 건 파라미터 개수만의 문제가 아닙니다. 옵티마이저 상태가 핵심입니다.

  • 그래디언트와 옵티마이저 상태는 학습하는 파라미터에 대해서만 생깁니다.
  • 원본 가중치를 동결하면 그 거대한 부분에는 그래디언트·옵티마이저 상태가 아예 안 생깁니다.

앞서 7B 풀 파인튜닝이 50GB+였다면, LoRA는 원본 가중치(추론용, 14GB)만 올려두고 아주 작은 어댑터에 대해서만 학습 상태를 유지하므로 한 자릿수 GB 수준으로 떨어집니다. 소비자용 GPU에서도 돌릴 수 있게 되는 겁니다.


4. QLoRA - 4bit 양자화를 얹기

LoRA를 써도 원본 가중치 14GB를 GPU에 올려두는 것 자체는 여전히 부담입니다. QLoRA는 여기를 공략합니다.

QLoRA = 원본을 4bit로 양자화해서 올려두고 + 그 위에 LoRA 어댑터를 학습

4-1. 양자화란

양자화(quantization)는 숫자의 정밀도를 낮춰 저장 용량을 줄이는 것입니다. fp16(16bit)을 4bit로 바꾸면 저장 크기가 1/4이 됩니다. 14GB짜리 원본이 약 3.5GB로 줄어듭니다.

fp16 가중치 (16bit) ──양자화──▶ 4bit 가중치 (동결, 추론에만 사용) 그 위에 LoRA 어댑터(고정밀)만 학습

4-2. QLoRA의 포인트

  • NF4(4bit NormalFloat): 가중치 분포에 맞춘 4bit 표현으로 정보 손실을 줄입니다.
  • 이중 양자화(double quantization): 양자화에 쓰는 상수까지 한 번 더 양자화해 메모리를 추가로 아낍니다.
  • 핵심: 무거운 원본은 4bit로 얼려두고, 실제 학습은 고정밀 LoRA 어댑터에서만 일어납니다. 그래서 양자화로 인한 정밀도 손실이 학습 품질에 크게 영향을 주지 않습니다.

이 조합 덕분에 예전이라면 A100 여러 장이 필요했을 규모의 모델을 단일 GPU 한 장에서 파인튜닝할 수 있게 됐습니다. QLoRA가 개인·소규모 팀의 파인튜닝을 대중화한 이유입니다.


5. 어댑터의 진짜 장점 - 가볍게 교체

LoRA/QLoRA의 결과물은 원본 크기의 새 모델이 아니라 수십 MB짜리 어댑터 파일입니다. 이게 운영 관점에서 큰 이점을 줍니다.

  • 원본 하나 + 어댑터 여러 개: 베이스 모델은 그대로 두고, 고객사별·태스크별 어댑터만 바꿔 끼웁니다.
  • 핫스왑: 요청에 따라 어댑터를 런타임에 갈아 끼우는 서빙도 가능합니다.
  • 버전 관리가 가볍다: 어댑터만 git이나 저장소에 올리면 되니 배포·롤백이 쉽습니다.
  • 병합 선택권: 배포 시 어댑터를 원본에 병합(merge)해 단일 모델로 만들 수도, 분리해 둘 수도 있습니다.
┌─ 어댑터: 고객상담 말투 베이스 ─┼─ 어댑터: 법무 문서 요약 (공유) └─ 어댑터: 코드 리뷰

USB에 여러 앱을 담아두고 필요할 때 꽂는 느낌에 가깝습니다.


6. 언제 무엇을 쓰나

먼저 큰 갈림길부터 짚습니다. 파인튜닝은 "무엇을 아는가(지식)"가 아니라 "어떻게 말하는가(형식·말투·도메인 감각)" 를 바꾸고 싶을 때 쓰는 도구입니다. 최신 지식 주입이 목적이라면 RAG가 먼저입니다.

그 위에서 파인튜닝 방식을 고른다면:

상황추천
데이터·GPU가 넉넉하고 최고 성능이 필요풀 파인튜닝
일반적인 도메인 적응, 자원 제한LoRA
GPU 한 장, 큰 모델을 어떻게든 튜닝QLoRA
지식만 최신화하고 싶다파인튜닝 아닌 RAG

실무 감각으로는 대부분 LoRA부터 시작합니다. 데이터 수백~수천 건으로 말투나 출력 형식을 잡는 정도라면 LoRA로 충분한 경우가 많습니다. GPU가 정말 빠듯하면 QLoRA로 내려가고, LoRA로도 품질이 안 나오면 데이터 품질을 먼저 의심한 뒤 풀 파인튜닝을 고려합니다.

주의점도 있습니다.

  • 랭크가 만능은 아니다: r을 무작정 키운다고 성능이 비례해 오르지 않습니다. 8/16부터 실험합니다.
  • 양자화는 추론 속도와 별개: QLoRA의 4bit는 학습 메모리 절감이 목적이고, 서빙 최적화는 또 다른 이야기입니다.
  • 데이터가 전부: 파인튜닝 성패는 기법보다 학습 데이터의 품질과 일관성에서 갈립니다.

마무리

LoRA는 "원본은 얼리고 작은 어댑터만 학습한다", QLoRA는 거기에 "원본을 4bit로 눌러 담는다" 를 더한 기법입니다. 덕분에 예전엔 대형 팀만 하던 파인튜닝을 이제 GPU 한 장으로도 시도할 수 있게 됐습니다.

처음 시작한다면 이 순서를 권합니다.

  1. 파인튜닝이 정말 필요한지부터 확인한다(지식 문제라면 RAG).
  2. 작은 데이터셋으로 LoRA(r=8~16) 부터 돌려본다.
  3. GPU가 부족하면 QLoRA로, 품질이 부족하면 데이터부터 개선한다.

"모델을 통째로 다시 학습"이 아니라 "필요한 만큼만 얹는다" 가 요즘 파인튜닝의 기본기입니다.

me

강경원

Backend Developer

성능과 안정성으로 신뢰받는 백엔드 개발자 · 요즘은 AI/LLM을 서비스에 접목합니다

이력서 보기