ChatGPT와 같은 거대 언어 모델(LLM)이 IT 생태계를 바꾸고 있지만, 실제 비즈니스에 적용하려 할 때 우리는 몇 가지 명확한 한계에 부딪힙니다. 모델이 학습하지 않은 최신 정보를 모르거나, 기업 내부 데이터에 접근할 수 없으며, 때로는 사실이 아닌 정보를 그럴듯하게 지어내는 ‘환각(Hallucination)’ 현상을 보이기 때문입니다.
이러한 문제를 해결하기 위해 등장한 가장 현실적이고 강력한 기술이 바로 RAG(Retrieval-Augmented Generation, 검색 증강 생성)입니다. RAG는 LLM이 답변을 생성할 때, 외부 또는 내부의 신뢰할 수 있는 데이터 소스를 실시간으로 ‘검색’하고, 그 결과를 ‘참고’하여 답변의 정확성과 신뢰도를 획기적으로 높이는 방식입니다.
왜 Custom RAG 인가?
“ChatGPT에 파일을 업로드하는 것도 RAG 아닌가요?”라고 생각할 수 있습니다. 맞습니다. 하지만 이 방식은 결정적인 한계를 가집니다. 바로 ‘블랙박스’라는 점입니다. 내부 동작을 알 수 없어 왜 특정 답변이 나왔는지, 혹은 왜 정보를 찾지 못했는지 파악하고 개선하기가 어렵습니다.
실제로 특정 문서의 상세 정보를 질문했을 때, 정보가 있음에도 “자료를 찾을 수 없다”고 답변하는 사례는 흔하게 발생합니다.
따라서 우리가 직접 RAG 파이프라인의 모든 구성 요소를 제어하고 최적화하는 Custom RAG가 중요합니다. Custom RAG는 다음과 같은 명확한 장점을 제공합니다.
- 투명성과 제어: 데이터 처리부터 검색, 답변 생성까지 전 과정을 추적하고 디버깅할 수 있습니다.
- 성능 최적화: 우리 데이터에 가장 적합한 임베딩 모델, 벡터 DB, 검색 전략을 선택해 성능을 극대화할 수 있습니다.
- 안정적인 환각 억제: 답변의 근거를 명확히 하고, 검색된 내용에 기반해서만 답변하도록 강제하여 환각을 효과적으로 제어할 수 있습니다.
이제 RAG를 구성하는 핵심 요소들을 하나씩 살펴보겠습니다.
RAG(Retrieval-Augmented Generation)란?
RAG는 문서 기반 검색을 통해 관련 데이터를 추출하고, 이를 LLM이 활용하여 답변을 생성하는 기술입니다. 전체 파이프라인은 크게 데이터를 준비하는 전처리 단계
와 질문에 답변하는 서비스 단계
로 나뉩니다.
1
2
3
4
5
6
7
8
9
RAG 파이프라인 구조
─────────────────────────────────────────────────────────────────
전처리 단계:
문서 → 문서 로더 → 텍스트 분할 → 임베딩 → 벡터 DB 저장
(Chunking)
─────────────────────────────────────────────────────────────────
서비스 단계:
질문 → 임베딩 → 검색(Retrieve) → LLM 처리 → 답변 생성
─────────────────────────────────────────────────────────────────
주요 RAG 구성 요소 상세 분석
1. 문서 로더 (Document Loader)
RAG의 첫 단계는 다양한 포맷의 문서를 시스템으로 불러오는 것입니다. 어떤 로더를 사용하느냐에 따라 초기 데이터의 품질이 결정됩니다.
로더 종류 | 장점 | 단점 | 추천 사용 사례 |
---|---|---|---|
PyPDF | 매우 빠른 속도 | 문장이 잘릴 수 있음 | 실시간 요약 등 빠른 처리가 필요할 때 |
PyPDFLoader | 한글 처리 우수, 준수한 속도 | - | 가장 일반적인 PDF 처리 |
UnstructuredPDF | 테이블, 제목 등 요소별 정보 추출 | 속도가 느림 | 문서의 상세한 구조 정보가 필요할 때 |
PDFPlumber | 인코딩 우수, 풍부한 메타데이터 제공 | 읽기 속도가 느림 | 메타데이터 기반 작업이 중요할 때 |
2. 텍스트 분할기 (Text Splitter)
긴 문서는 LLM이 한 번에 처리하기 어렵기 때문에 의미 있는 작은 단위인 ‘청크(Chunk)’로 나누어야 합니다.
- 강력 추천:
RecursiveCharacterTextSplitter
는 단락 → 문장 → 단어 순으로 계층적으로 분할을 시도하여 의미 단위의 손실을 최소화합니다. - 한국어 특화:
KoNLPyTextSplitter
는 한국어 형태소 분석기를 사용하여 더 정교한 분할이 가능하지만, 처리 속도가 느릴 수 있습니다. - 최신 기법:
SemanticChunker
는 문장의 의미적 유사성을 기반으로 자동으로 텍스트를 분할하는 새로운 접근법입니다.
3. 임베딩 (Embedding) 및 벡터 저장소 (Vector Store)
임베딩은 텍스트 청크를 검색 가능한 숫자 벡터로 변환하는 과정입니다.
- 모델 선택: OpenAI의 임베딩 모델은 사용이 간편하고 성능이 우수하며, Hugging Face에서는 다양한 무료 오픈소스 모델을 선택할 수 있습니다. 한국어 처리 성능을 반드시 벤치마킹해야 합니다.
- 비용 절약 팁:
Cache-backed Embedding
을 활용하면, 한 번 임베딩한 결과를 로컬에 저장해두고 재사용하여 중복 API 호출 비용을 줄일 수 있습니다.
변환된 벡터들은 벡터 저장소(Vector Store)에 저장됩니다. 클라우드 환경에서는 Pinecone
, Milvus
등을, 로컬에서는 FAISS
, Chroma DB
등을 주로 사용합니다.
4. 검색기 (Retriever)
사용자 질문에 가장 관련성 높은 문서를 벡터 DB에서 찾아내는 핵심 엔진입니다. 단순 검색을 넘어 다음과 같은 고급 전략을 사용할 수 있습니다.
- Multi-Query Retriever: 하나의 질문을 LLM을 통해 여러 유사한 질문으로 변형시켜 검색함으로써, 사용자의 숨은 의도까지 파악하여 검색 범위를 넓힙니다.
- Ensemble Retriever: 키워드 기반 검색(Sparse, 예: BM25)의 정확성과 의미 기반 벡터 검색(Dense)의 풍부함을 결합하여 검색 품질을 극대화합니다.
- Long Context Reorder: LLM이 긴 문맥의 중간 부분을 놓치는 경향(‘Lost in the middle’)을 보완하기 위해, 검색된 문서 중 가장 중요한 것을 맨 앞과 맨 뒤로 재배치하는 전략입니다.
전문가를 위한 RAG 응용 전략
기본 파이프라인을 구축했다면, 다음 전략들로 RAG 시스템의 성능을 한 차원 더 높일 수 있습니다.
- 불필요한 영역 제거: 문서의 머리글, 바닥글, 페이지 번호 등 반복적이고 무의미한 부분은 전처리 단계에서 제거하여 검색 노이즈를 줄입니다.
- 테이블/이미지 추출:
Camelot
,PaddleOCR
과 같은 라이브러리를 사용해 PDF 내의 표나 이미지 속 텍스트를 정확하게 추출하고 별도로 처리합니다. - 메타데이터 필터링: 문서의 생성 날짜, 카테고리, 작성자 등의 메타데이터를 함께 저장하고, 검색 시 필터 조건으로 활용하여 검색 범위를 효과적으로 좁힐 수 있습니다.
- 고급 요약 (Chain of Density): 검색된 문서들을 단순히 LLM에 전달하는 대신, 여러 단계에 걸쳐 요약을 반복하며 핵심 정보를 누락 없이 압축하는 기법입니다.
- 프롬프트 관리: 시스템 프롬프트를
YAML
파일 등으로 버전 관리하고,LangChain Hub
와 같은 도구를 활용하여 검증된 프롬프트 템플릿을 재사용합니다.
지금까지 RAG의 개념과 핵심 구성 요소, 그리고 실제 구현을 위한 여러 전략을 살펴보았습니다. 성공적인 RAG 시스템은 단순히 기술을 적용하는 것을 넘어, 데이터의 특성에 맞춰 각 구성 요소를 어떻게 선택하고 튜닝하느냐에 따라 그 성능이 결정됩니다.
안정적이고 신뢰도 높은 AI 서비스 구현에 있어 RAG는 매우 강력한 도구입니다. 이 글이 여러분의 프로젝트에 적합한 RAG 아키텍처를 설계하는 데 실질적인 도움이 되었기를 바랍니다.