· RAG는 LLM이 답하기 직전에 관련 문서를 검색해 프롬프트에 끼워 넣는 기법이에요.
· 재학습 없이 최신·사내 지식을 반영해 환각(지어내기)을 크게 줄여줍니다.
· 성패는 사실상 검색 품질에 달려 있어요.
→
🔢 임베딩
→
🗄️ 벡터DB 저장
→
🔍 검색
→
✍️ 답 생성
챗봇에게 “우리 회사 규정 알려줘”라고 물으면, 모델은 그럴듯하지만 틀린 답을 자신 있게 내놓곤 합니다. 학습 데이터에 없는 내용을 지어내는 이른바 환각(hallucination)입니다. 이 문제를 실무에서 가장 현실적으로 줄이는 방법이 바로 RAG(Retrieval-Augmented Generation, 검색증강생성)입니다.
🔍 RAG란 무엇인가 — ‘오픈북 시험’에 비유하기
일반적인 LLM은 외운 것만으로 시험을 보는 학생과 같습니다. 배운 범위 밖의 질문이 나오면 기억을 쥐어짜다 결국 지어냅니다. 반면 RAG는 오픈북 시험입니다. 질문을 받으면 먼저 관련 자료를 찾아서 책상에 펼쳐 놓고, 그 자료를 근거로 답을 씁니다.
RAG는 모델을 다시 학습시키는 게 아니라, 답을 생성하기 직전에 관련 문서를 검색해 프롬프트에 끼워 넣는 방식입니다.
⚙️ RAG의 동작 4단계
💻 흐름을 코드로 감 잡기
실제 구현은 라이브러리마다 다르지만, 뼈대는 아래처럼 단순합니다.
# 1) 문서를 조각내고 임베딩해 벡터DB에 저장 (최초 1회)
chunks = split_documents(load("사내_규정.pdf"), size=800, overlap=100)
vectordb = VectorDB.from_texts(chunks, embedding=EmbeddingModel())
# 2) 질문이 들어오면: 검색 → 프롬프트 조립 → 생성
def answer(question):
docs = vectordb.search(question, top_k=4) # 관련 조각 4개
context = "\n\n".join(docs)
prompt = f"다음 자료만 근거로 답하라.\n[자료]\n{context}\n\n[질문] {question}"
return llm.generate(prompt)
포인트는 검색으로 찾은 context를 프롬프트에 넣는다는 것 하나입니다.
⚖️ RAG가 빛나는 상황과 한계
| ✅ 잘 맞는 경우 | ⚠️ 한계 |
|---|---|
| 사내 문서 Q&A, 고객지원 봇, 제품 매뉴얼 검색처럼 ‘출처가 분명한 지식’. 근거 문서를 함께 보여줘 신뢰성이 올라감. | 검색이 엉뚱한 조각을 가져오면 생성도 무너짐. 성패는 검색 품질에 달림. 문서에 없는 내용은 답 못 함. |
💡 직접 만들 때 챙길 실무 팁
- 청크 크기·중첩 — 800자 안팎 + 100자 중첩이 무난한 출발점.
- 임베딩 모델 — 한국어 문서라면 한국어 성능이 검증된 임베딩을 선택.
- 재순위(Re-ranking) — 후보를 넉넉히 뽑은 뒤 다시 순위를 매기면 정확도가 크게 오름.
- 근거 표시 — 답변과 함께 참고 문서를 노출하면 신뢰·검증에 유리.
- 프롬프트 방어 — “자료에 없으면 모른다고 답하라”로 환각을 한 번 더 억제.
❓ 자주 묻는 질문 (FAQ)
Q. RAG와 파인튜닝(재학습)은 뭐가 다른가요?
A. 파인튜닝은 모델 자체를 다시 학습시키는 것이고, RAG는 학습은 그대로 두고 답할 때 자료를 찾아 붙여주는 방식이에요. 자주 바뀌는 지식엔 RAG가 훨씬 가볍고 빠릅니다.
Q. 문서가 몇 개 없어도 효과가 있나요?
A. 네. 문서가 적어도 ‘정답이 그 안에 있다면’ 잘 동작해요. 오히려 문서가 지저분하거나 검색이 부정확할 때 품질이 떨어집니다.
Q. 꼭 벡터DB가 필요한가요?
A. 소규모면 메모리 기반(FAISS)만으로 충분하고, 데이터가 커지면 pgvector·전용 벡터DB로 확장하면 됩니다.
마무리
RAG는 거창한 재학습 없이도 LLM을 ‘우리 데이터’에 연결하는 가장 실용적인 다리입니다. 핵심은 단순합니다 — 좋은 자료를 잘 찾아서, 그 근거로 답하게 만드는 것. 그래서 모델 자체보다 검색 품질과 데이터 정리에 공을 들이는 팀이 결국 더 좋은 결과를 얻습니다.
댓글 남기기