
파인튜닝 vs 프롬프트 엔지니어링
LLM 커스터마이징 방법인 파인튜닝과 프롬프트 엔지니어링의 차이와 선택 기준

LLM 커스터마이징 방법인 파인튜닝과 프롬프트 엔지니어링의 차이와 선택 기준
AI 시대의 금광, 엔비디아 GPU. 도대체 게임용 그래픽카드로 왜 AI를 돌리는 걸까? 단순 노동자(CUDA)와 행렬 계산 천재(Tensor)의 차이로 파헤쳐봤습니다.

AI와 딥러닝은 왜 CPU를 버리고 GPU를 선택했을까요? ALU 구조 차이부터 CUDA 메모리 계층, 그래픽 API(Vulakn/DirectX), 그리고 생성형 AI의 원리까지 하드웨어 가속의 모든 것을 다룹니다.

신경망의 동작 원리를 프로젝트 경험을 통해 이해한 과정. 공장 라인 비유부터 역전파, 하이퍼파라미터 튜닝까지.

Transformer 아키텍처의 동작 원리를 경험을 통해 이해한 과정

LLM을 우리 서비스에 맞게 커스터마이징하려고 했습니다. 두 가지 방법이 있었습니다: 파인튜닝과 프롬프트 엔지니어링. 어떤 걸 선택해야 할까?
파인튜닝은 비용이 높지만 성능이 좋다고 하고, 프롬프트 엔지니어링은 간단하지만 한계가 있다고 합니다. 실제로 둘 다 시도해보고 차이를 이해했습니다.
가장 혼란스러웠던 부분은 "언제 파인튜닝을 하고 언제 프롬프트만 쓰나?"였습니다.
또 다른 혼란은 "파인튜닝이 항상 더 좋은 거 아닌가?"였습니다. 비용과 시간을 들여서 모델을 학습시키는데, 당연히 더 좋지 않을까?
그리고 "프롬프트 엔지니어링으로 충분한 경우는 언제인가?"도 헷갈렸습니다.
이해하는 데 결정적이었던 비유는 "요리사 교육"이었습니다.
프롬프트 엔지니어링 = 레시피 주기:이 비유로 이해했습니다. 프롬프트 엔지니어링은 빠르고 유연하지만, 파인튜닝은 특정 작업에 특화된 성능을 낸다는 것을.
모델을 변경하지 않고, 입력(프롬프트)만 잘 설계해서 원하는 결과를 얻습니다.
# 기본 프롬프트
prompt = "이 리뷰를 분석해줘: 이 제품 정말 좋아요!"
response = llm(prompt)
# 개선된 프롬프트 (Few-shot)
prompt = """
다음 리뷰들을 보고 감정을 분석해줘:
리뷰: "최고의 제품입니다"
감정: 긍정
리뷰: "별로예요"
감정: 부정
리뷰: "이 제품 정말 좋아요!"
감정:
"""
response = llm(prompt) # "긍정"
from openai import OpenAI
client = OpenAI()
# System prompt로 역할 정의
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "당신은 친절한 고객 서비스 챗봇입니다."},
{"role": "user", "content": "환불하고 싶어요"}
]
)
print(response.choices[0].message.content)
모델 자체를 특정 작업에 맞게 재학습시킵니다. 기존 모델의 가중치를 업데이트합니다.
# 학습 데이터 준비
training_data = [
{"prompt": "리뷰: 최고예요", "completion": "긍정"},
{"prompt": "리뷰: 별로예요", "completion": "부정"},
# ... 수백~수천 개
]
# 파인튜닝
fine_tuned_model = finetune(base_model, training_data)
# 사용
response = fine_tuned_model("리뷰: 좋아요") # "긍정"
from openai import OpenAI
client = OpenAI()
# 1. 학습 데이터 업로드
with open("training_data.jsonl", "rb") as f:
training_file = client.files.create(file=f, purpose="fine-tune")
# 2. 파인튜닝 시작
fine_tune_job = client.fine_tuning.jobs.create(
training_file=training_file.id,
model="gpt-3.5-turbo"
)
# 3. 파인튜닝된 모델 사용
response = client.chat.completions.create(
model=fine_tune_job.fine_tuned_model,
messages=[{"role": "user", "content": "리뷰: 좋아요"}]
)
| 특징 | 프롬프트 엔지니어링 | 파인튜닝 |
|---|---|---|
| 시작 시간 | 즉시 | 수 시간~수 일 |
| 비용 | API 호출 비용 | 학습 비용 + API 비용 |
| 데이터 | 불필요 | 수백~수천 개 필요 |
| 성능 | 중간 | 높음 |
| 일관성 | 낮음 | 높음 |
| 유연성 | 높음 | 낮음 |
| 유지보수 | 쉬움 | 어려움 |
# 예시 - 다목적 챗봇
def chatbot(user_input, task_type):
if task_type == "translation":
prompt = f"Translate to English: {user_input}"
elif task_type == "summary":
prompt = f"Summarize: {user_input}"
elif task_type == "sentiment":
prompt = f"Analyze sentiment: {user_input}"
return llm(prompt)
# 예시 - 의료 진단 보조
# 수천 개의 의료 데이터로 파인튜닝
medical_model = finetune(base_model, medical_data)
# 일관되고 정확한 진단 보조
diagnosis = medical_model("증상: 두통, 발열, 기침")
제가 실제로 프로젝트에서 사용한 경험입니다.
목표: 다양한 고객 문의 처리
선택: 프롬프트 엔지니어링
이유:
구현:
system_prompt = """
당신은 친절한 고객 서비스 챗봇입니다.
- 항상 존댓말 사용
- 문제 해결 중심
- 필요시 상담원 연결
"""
response = llm(system_prompt + user_query)
결과: 2주 만에 배포, 고객 만족도 80%
목표: 계약서에서 위험 조항 찾기
선택: 파인튜닝
이유:
구현:
# 1000개 계약서로 파인튜닝
legal_model = finetune(
base_model="gpt-3.5-turbo",
training_data=legal_contracts
)
# 정확하고 일관된 분석
risks = legal_model.analyze(contract)
결과: 정확도 95%, 변호사 검토 시간 70% 감소
목표: 리뷰 긍정/부정 분류
1차 시도: 프롬프트 엔지니어링
2차 시도: 파인튜닝
결론: 파인튜닝으로 전환 → 성능 향상 + 비용 절감
최근에는 둘을 결합하는 방법이 인기입니다.
프롬프트에 관련 정보를 자동으로 추가:
# 1. 관련 문서 검색
relevant_docs = vector_db.search(user_query)
# 2. 프롬프트에 포함
prompt = f"""
참고 문서:
{relevant_docs}
질문: {user_query}
답변:
"""
response = llm(prompt)
파인튜닝된 모델에 프롬프트로 세부 조정:
# 파인튜닝된 모델
fine_tuned_model = load_model("my-fine-tuned-model")
# 프롬프트로 세부 조정
prompt = f"""
형식: JSON
필드: sentiment, confidence, reason
리뷰: {review}
"""
response = fine_tuned_model(prompt)
# GPT-4 API 비용 (2024년 기준)
# 입력: $0.03 / 1K tokens
# 출력: $0.06 / 1K tokens
# 예시 - 월 10만 건 처리
# 평균 프롬프트: 500 tokens
# 평균 응답: 200 tokens
monthly_cost = (
100_000 * 500 / 1000 * 0.03 + # 입력
100_000 * 200 / 1000 * 0.06 # 출력
) = $1,500 + $1,200 = $2,700
# GPT-3.5 파인튜닝 비용
# 학습: $0.008 / 1K tokens
# 사용 - $0.012 / 1K tokens (입력 + 출력)
# 초기 학습 비용 (1회)
training_cost = 5_000 * 500 / 1000 * 0.008 = $20
# 월 사용 비용
# 프롬프트가 짧아짐 (100 tokens)
monthly_cost = (
100_000 * 100 / 1000 * 0.012
) = $120
# 총 비용 (첫 달)
total = $20 + $120 = $140
결론: 대량 처리 시 파인튜닝이 훨씬 저렴!
먼저 프롬프트로 시도해보고, 한계에 부딪히면 파인튜닝 고려:
# 1단계 - 기본 프롬프트
result = llm("Classify: " + text)
# 2단계 - Few-shot 프롬프트
result = llm(few_shot_prompt + text)
# 3단계: Chain-of-Thought
result = llm(cot_prompt + text)
# 4단계 - 파인튜닝 고려
if accuracy < 90%:
consider_finetuning()
파인튜닝 시 데이터 품질이 가장 중요:
# 나쁜 예 - 노이즈가 많은 데이터
bad_data = [
{"prompt": "good", "completion": "positive"}, # 너무 짧음
{"prompt": "bad product!!!", "completion": "neg"}, # 오타
]
# 좋은 예 - 깨끗하고 일관된 데이터
good_data = [
{"prompt": "Review: This product is excellent", "completion": "positive"},
{"prompt": "Review: Not satisfied with quality", "completion": "negative"},
]
한 번에 완벽하게 하려 하지 말고, 점진적으로 개선:
# 1차 - 기본 프롬프트
v1 = basic_prompt(text)
# 2차 - 예시 추가
v2 = few_shot_prompt(text)
# 3차 - 100개 데이터로 파인튜닝
v3 = finetune(model, data_100)
# 4차 - 1000개 데이터로 파인튜닝
v4 = finetune(model, data_1000)
# GPT-4 API 비용 (2024년 기준)
# 입력: $0.03 / 1K tokens
# 출력: $0.06 / 1K tokens
# 예시 - 월 10만 건 처리
# 평균 프롬프트: 500 tokens
# 평균 응답: 200 tokens
monthly_cost = (
100_000 * 500 / 1000 * 0.03 + # 입력
100_000 * 200 / 1000 * 0.06 # 출력
) = $1,500 + $1,200 = $2,700
# GPT-3.5 파인튜닝 비용
# 학습: $0.008 / 1K tokens
# 사용 - $0.012 / 1K tokens (입력 + 출력)
# 초기 학습 비용 (1회)
training_cost = 5_000 * 500 / 1000 * 0.008 = $20
# 월 사용 비용
# 프롬프트가 짧아짐 (100 tokens)
monthly_cost = (
100_000 * 100 / 1000 * 0.012
) = $120
# 총 비용 (첫 달)
total = $20 + $120 = $140
결론: 대량 처리 시 파인튜닝이 훨씬 저렴!
먼저 프롬프트로 시도해보고, 한계에 부딪히면 파인튜닝 고려:
# 1단계 - 기본 프롬프트
result = llm("Classify: " + text)
# 2단계 - Few-shot 프롬프트
result = llm(few_shot_prompt + text)
# 3단계: Chain-of-Thought
result = llm(cot_prompt + text)
# 4단계 - 파인튜닝 고려
if accuracy < 90%:
consider_finetuning()
파인튜닝 시 데이터 품질이 가장 중요:
# 나쁜 예 - 노이즈가 많은 데이터
bad_data = [
{"prompt": "good", "completion": "positive"}, # 너무 짧음
{"prompt": "bad product!!!", "completion": "neg"}, # 오타
]
# 좋은 예 - 깨끗하고 일관된 데이터
good_data = [
{"prompt": "Review: This product is excellent", "completion": "positive"},
{"prompt": "Review: Not satisfied with quality", "completion": "negative"},
]
한 번에 완벽하게 하려 하지 말고, 점진적으로 개선:
# 1차 - 기본 프롬프트
v1 = basic_prompt(text)
# 2차 - 예시 추가
v2 = few_shot_prompt(text)
# 3차 - 100개 데이터로 파인튜닝
v3 = finetune(model, data_100)
# 4차 - 1000개 데이터로 파인튜닝
v4 = finetune(model, data_1000)
프롬프트 엔지니어링과 파인튜닝은 LLM 커스터마이징의 두 가지 주요 방법입니다. 프롬프트 엔지니어링은 빠르고 유연하지만 성능과 일관성에 한계가 있고, 파인튜닝은 높은 성능과 일관성을 제공하지만 시간과 비용이 듭니다.
저는 대부분의 프로젝트를 프롬프트 엔지니어링으로 시작합니다. 빠르게 프로토타입을 만들고, 실제 사용하면서 한계를 파악합니다. 그리고 정말 필요한 경우에만 파인튜닝으로 전환합니다. 이렇게 하면 시간과 비용을 절약하면서도 최적의 결과를 얻을 수 있습니다. 데이터를 기반으로 의사결정하는 것이 핵심입니다. 사용자의 니즈를 최우선으로 고려해야 합니다.
핵심은 "비용 대비 효과"입니다. 프롬프트로 충분하면 굳이 파인튜닝할 필요 없습니다. 하지만 대량 처리, 높은 정확도, 일관성이 중요하다면 파인튜닝이 답입니다.