
사내 RAG 시스템 구축에서 자주 부딪히는 5가지 실패 사례 (그리고 해결책)
- AI
- Exienent
- · 수정
**RAG(Retrieval-Augmented Generation, 검색 증강 생성)**를 실제 프로덕션에서 굴리는 일은 "문서를 벡터 DB에 넣고 LLM을 연결하면 끝"이 아닙니다. 사내 RAG는 문서 파싱, 청킹, 데이터 최신성, 환각, 컨텍스트 비용이라는 다섯 지점에서 무너지기 쉽고, 해법은 화려한 AI 프레임워크가 아니라 데이터 엔지니어링에 있습니다.
최근 모든 기업이 'AI 도입'을 외치며 가장 먼저 시도하는 것이 바로 RAG 기반의 사내 챗봇 또는 지식 검색 시스템입니다. "사내 문서를 벡터 DB에 넣고 LLM(대형 언어 모델)을 연결하면 끝!"이라는 벤더사들의 감언이설에 속아 프로젝트를 시작하셨다면, 지금쯤 깊은 좌절감을 맛보고 계실 수도 있습니다.
방대한 사내 문서(PDF, Word, Confluence 등)를 활용한 RAG 시스템은 처참한 실패와 멘붕의 연속이 되기 쉽습니다. 튜토리얼 수준을 넘어 실제 프로덕션 환경에서 RAG를 굴릴 때 마주치는 현실적인 문제 5가지와 해결 방법을 정리합니다.
1. RAG는 왜 표와 이미지를 무시할까요? - 더러운 데이터 파싱의 저주
RAG가 표와 이미지를 무시하는 이유는 일반 텍스트 파서가 이를 제대로 읽지 못하기 때문입니다. 랭체인(LangChain) 튜토리얼에서는 결코 알려주지 않는 '문서 파싱(Parsing)'의 현실이죠.
사내 문서는 PDF와 PPT인 경우가 많은데, 이 문서들은 예쁜 텍스트로만 이루어진 게 아니라 복잡한 2단 표, 다이어그램, 스캔본 이미지가 뒤섞여 있습니다. 일반적인 PDF 파서(PyPDF 등)를 돌리면 표 안의 데이터가 순서도 없이 뒤죽박죽으로 추출되어 벡터 DB에 들어갈 수 있습니다.
그러면 AI는 엉뚱한 답변을 내놓습니다. "2025년 3분기 매출액은 얼마인가요?"라고 물어보면, 표의 헤더와 본문을 매칭하지 못해 헛소리를 하게 되죠.
🛠 어떻게 해결할까? (Vision 모델의 도입) 단순 텍스트 파싱을 포기하고, Multimodal LLM(Vision 기능이 있는 모델)과 OCR을 결합한 파이프라인을 구축합니다. 복잡한 표나 레이아웃이 있는 페이지는 아예 이미지로 캡처한 뒤, LLM에게 "이 이미지를 Markdown 형식의 표로 정확히 변환해줘"라고 지시하여 텍스트화한 후 임베딩합니다. 비용과 파싱 시간은 늘어나지만, 정보 검색 정확도를 크게 끌어올릴 수 있습니다.
2. 문서는 어떻게 청킹해야 할까요? - 쪼개면 맥락을 잃고, 합치면 노이즈가 된다
문서는 고정 크기가 아니라 의미 단위로 잘라야 합니다. 문서를 벡터 DB에 넣기 위해 적당한 크기로 자르는 청킹(Chunking) 작업은 많은 RAG 프로젝트가 지옥을 맛보는 구간입니다.
토큰 수 1,000개 같은 단위로 기계적으로 문서를 자르면(Fixed-size chunking), 문서의 중요한 문맥이 A 청크와 B 청크 사이에서 동강 날 수 있습니다. "이 정책의 예외 사항은..."으로 A가 끝나고, B는 "다음과 같습니다."로 시작하는 식이죠. 이렇게 잘린 조각을 검색해서 LLM에게 주면 맥락을 전혀 이해하지 못합니다.
🛠 어떻게 해결할까? (Semantic Chunking & Parent-Child 구조) 기계적인 분할 대신, 의미 기반(Semantic) 분할과 Parent-Child Retrieval 방식을 도입합니다.
- 문서를 '의미'가 연결되는 단위(단락이나 섹션 단위)로 쪼갭니다.
- 벡터 DB에는 아주 작게 자른 Child 청크를 저장하여 '정밀한 검색'을 가능하게 합니다.
- 하지만 실제 LLM에게 컨텍스트를 던져줄 때는, 검색된 Child가 속한 **전체 원본 문단(Parent Chunk)**을 통째로 넘겨주어 맥락 상실을 방지합니다.
3. RAG는 왜 폐기된 문서를 인용할까요? - 동적 데이터 동기화의 지옥
RAG가 폐기된 문서를 인용하는 이유는 원본이 바뀌어도 벡터 DB가 따라 바뀌지 않기 때문입니다. RAG 시스템을 사내에 오픈하면 "AI가 옛날 규정을 정답인 것처럼 말해요!" 같은 클레임이 들어올 수 있습니다.
사내 규정, 메뉴얼, 부서 정보는 매일 업데이트됩니다. 하지만 벡터 DB는 일주일 전에 밀어 넣은 과거 데이터에 머물러 있곤 하죠. 파일 시스템이나 Confluence의 변경 사항을 실시간으로 감지해서 벡터 DB의 특정 청크만 업데이트하거나 삭제하는 과정은 상상 이상으로 복잡합니다.
🛠 어떻게 해결할까? (Metadata 활용과 주기적 Sync) 모든 문서 청크에 문서 ID, 최종 수정일자, 버전, 접근 권한을 나타내는 메타데이터(Metadata)를 철저하게 부여합니다. 그리고 배치(Batch) 스크립트를 작성해 매일 새벽 원본 시스템의 수정일자와 벡터 DB의 메타데이터를 비교하여, 변경/삭제된 문서의 벡터만 핀셋처럼 골라내어 재임베딩(Re-embedding)하는 파이프라인을 구축합니다.
4. RAG도 환각(Hallucination)을 할까요?
네, RAG도 환각을 합니다. 흔히 "RAG를 쓰면 문서에 있는 내용만 대답하니까 할루시네이션이 없다"고 오해하지만, 절대 아닙니다.
검색된 문서(Context)에 사용자가 원하는 정답이 아예 없는 경우, LLM은 자존심을 굽히지 않고 자신이 가진 사전 학습 지식을 동원해 그럴싸한 거짓말을 지어낼 수 있습니다. 특히 사내 은어나 약어가 섞인 질문을 받으면 소설을 쓰기 쉽습니다.
🛠 어떻게 해결할까? (Strict Prompting & 하이브리드 검색)
- 프롬프트 엔지니어링 강화: 시스템 프롬프트에 "반드시 제공된 Context 내에서만 답변해. Context에 정보가 부족하면 절대 지어내지 말고 '제공된 문서에서 정보를 찾을 수 없습니다'라고 말해." 라고 거듭 강조(협박)합니다.
- 하이브리드 검색(Hybrid Search) 도입: 벡터 기반의 의미 검색(Semantic Search)만으로는 '특정 제품명'이나 '부서 코드' 같은 정확한 키워드 검색에 취약합니다. 그래서 전통적인 키워드 검색 엔진(BM25, Elasticsearch 등)을 벡터 검색과 결합하여, 두 결과를 융합(Reciprocal Rank Fusion)하는 방식으로 검색 품질을 끌어올리고 엉뚱한 문서를 가져오는 일을 막을 수 있습니다.
5. RAG 비용은 왜 폭증할까요? - 너무 많은 Context가 부른 참사
RAG 비용이 폭증하는 이유는 검색된 문서를 매번 너무 많이 프롬프트에 밀어 넣기 때문입니다. 정확도를 높이겠다고 검색 엔진이 찾아온 관련 문서(Context) 10~20개를 그대로 LLM 프롬프트에 우겨넣으면, 답변은 잘 나와도 클라우드 청구서를 보고 경악할 수 있습니다.
질문할 때마다 수만 개의 토큰을 입력으로 소모하면 API 비용이 기하급수적으로 늘어납니다. 또한, 입력 컨텍스트가 너무 길어지면 LLM이 정작 중요한 중간 내용은 까먹는 'Lost in the middle' 현상까지 발생할 수 있습니다.
🛠 어떻게 해결할까? (Reranking 모델의 구원) 검색된 결과를 무식하게 다 밀어넣는 대신, Reranker (재순위화) 모델을 파이프라인 중간에 끼워 넣습니다.
- 초기 검색에서 관련 있을 법한 문서를 넉넉하게(예: 20개) 가져옵니다.
- 가볍고 빠른 Reranking 모델(Cross-Encoder 등)을 사용하여 사용자의 질문과 가장 연관성이 높은 문서 3~4개만 엄선하여 순위를 다시 매깁니다.
- 이 핵심적인 3~4개의 문서만 LLM에게 넘겨줍니다. 이렇게 하면 답변의 질은 유지하면서 토큰 사용량(비용)과 응답 지연 시간(Latency)을 크게 줄일 수 있습니다.
RAG의 본질은 무엇일까요? '검색 엔진' 공사입니다
RAG는 '마법의 AI 지팡이'가 아니라, 극도로 지루하고 정교한 데이터 엔지니어링이자 고도화된 검색 엔진(Search Engine)을 구축하는 노동입니다.
LLM의 성능을 탓하기 전에, **"우리가 LLM에게 얼마나 깨끗하고 정확한 문맥을 떠먹여 주고 있는가?"**를 먼저 고민해야 합니다. 사내 RAG 도입을 준비 중이시라면, 겉멋 든 AI 프레임워크보다 '데이터 정제 파이프라인'에 예산과 시간을 70% 이상 투자하시기를 강력히 권장합니다. 제 생각에는 그게 결국 실패를 줄이는 가장 빠른 지름길입니다.











