RAG 시스템 구축 실전기: 성공과 실패의 기록
From zero to a RAG system: successes and failures
TL;DR Highlight
1TB 규모의 회사 내부 기술 문서를 대상으로 로컬 LLM 기반 RAG 시스템을 처음부터 구축한 실전 경험담으로, 데이터 전처리부터 벡터 인덱싱까지 겪은 시행착오를 솔직하게 공유한다.
Who Should Read
사내 문서 검색이나 지식 베이스 구축을 위해 RAG 시스템을 처음 도입하려는 백엔드/ML 엔지니어, 특히 비정형 대용량 문서를 다루는 상황에서 어디서부터 시작해야 할지 막막한 개발자.
Core Mechanics
- 요구사항은 단순해 보였지만 실제로는 매우 복잡했다. 회사 10년치 프로젝트 전체에 대해 자연어 질의응답이 가능해야 하고, 빠른 응답속도, 외부 API 미사용(보안), OrcaFlex 같은 특수 시뮬레이션 파일까지 커버해야 했다. 주어진 데이터는 1TB짜리 Azure 폴더로, 수천 개의 파일이 형식도 구조도 없이 뒤섞인 상태였다.
- 기술 스택 선정 결과: 로컬 LLM 실행에는 Ollama, 임베딩 모델은 기술 문서에서 품질이 좋았던 nomic-embed-text, RAG 오케스트레이션(문서 인덱싱, 임베딩 생성, 벡터 DB 저장 및 쿼리)에는 오픈소스 프레임워크인 LlamaIndex를 선택했다. 언어는 Python을 사용했고, 초기 프로토타입은 적은 코드로도 잘 동작했다.
- 첫 번째 큰 장벽은 메모리 폭발이었다. LlamaIndex로 실제 문서를 처리하기 시작하자 수 기가바이트짜리 시뮬레이션 파일, 동영상 등을 텍스트처럼 통째로 메모리에 올리려 하면서 노트북이 다운됐다. 해결책으로 확장자별·파일명 패턴별 필터링 파이프라인을 추가해 mp4, exe, zip, .sim, .dat, 백업 파일 등 수십 가지 확장자를 처리 대상에서 제외했다.
- 파일 필터링 후에도 문제가 이어졌다. 텍스트 추출이 불가능한 스캔 PDF, 수백 MB짜리 CAD 파일, 암호화된 문서들이 파이프라인을 막았다. 파일 크기 상한선을 설정하고, 텍스트 추출 실패 시 건너뛰는 예외 처리를 추가하는 방식으로 대응했다.
- 인덱싱 작업 자체가 장기 프로젝트가 됐다. 노트북으로는 한계가 있어 Hetzner 클라우드 VM으로 작업을 옮겼고, 중단 없이 2~3주를 돌려서야 인덱싱이 완료됐다. 총 비용은 184유로였는데, 댓글에서는 '3주 인건비에 비하면 푼돈'이라는 반응이 많았다.
- 청킹(Chunking, 문서를 적절한 크기로 나누는 작업) 전략이 검색 품질을 크게 좌우했다. 너무 크게 자르면 관련 없는 내용이 섞이고, 너무 작게 자르면 맥락이 끊긴다. OrcaFlex 같은 특수 포맷 파일은 일반 텍스트 파서로는 의미 있는 청크를 만들기 어려워 별도 처리가 필요했다.
- 최종 교훈은 '데이터 전처리가 전부'라는 것이다. 좋은 임베딩 모델이나 벡터 DB를 선택하는 것보다, 어떤 데이터를 어떻게 정제해서 넣느냐가 RAG 시스템의 품질을 결정한다. 저자는 RAG를 처음 접했음에도 이 결론에 도달했고, 경험 많은 실무자들도 댓글에서 동의했다.
Evidence
- '데이터 전처리가 핵심'이라는 저자의 결론에 RAG 경험자들이 강하게 공감했다. 한 댓글러는 '20페이지짜리 PDF 하나에서 가격 정보를 100% 정확도로 뽑아내기 위해 SQL과 그래프 DB를 분리하는 ETL을 일주일 동안 만들었다'고 경험을 공유하며, 단순히 docling으로 PDF를 마크다운으로 변환하고 벡터 DB에 던지는 접근법은 '터무니없다'고 비판했다.
- 'RAG is dead'라는 주장에 대한 반론이 나왔다. LLM의 컨텍스트 창이 커져서 RAG가 불필요해진다는 주장에 대해, '반지의 제왕 전체가 컨텍스트에 들어갈 수 있다 해도, 법률 도서관 전체나 Wikipedia 전체, 혹은 이 글처럼 451GB 데이터는 여전히 몇 배나 크다'는 현실적인 반론이 제기됐다. 반면 한 댓글러는 RAG를 'AI Lite' 혹은 'AI 인접 기술'로 보며, 컨텍스트 창이 충분히 커지면 RAG의 결정론적 방식이 LLM의 추론 능력을 제한할 것이라고 전망했다.
- 재랭킹(Re-ranking) 미사용을 아쉬워하는 의견이 있었다. 한 댓글러는 '좋은 임베딩 모델을 썼는데 재랭커를 안 쓴 게 아쉽다. 재랭커를 쓰면 임베딩 모델은 작고 저렴한 것을 써도 되고, 오히려 더 작은 임베딩 벡터를 쓸 수 있어 유리하다'고 지적했다. 재랭킹은 벡터 검색으로 뽑은 후보 문서들을 LLM이 다시 한번 관련도 순으로 정렬하는 기법이다.
- 구조화된 데이터 전처리와 ReAG(추론 기반 RAG)를 언급하는 고급 의견도 나왔다. 한 댓글러는 '비정형 데이터를 그냥 벡터 DB에 던지는 대신, 기본적인 전처리와 라벨링을 하고, 다른 스키마로 임베딩하면 검색 품질과 유연성이 크게 올라간다. 여기에 메모리 지식 그래프까지 더하면 정적 문서를 넘어 시간에 따라 업데이트되는 컨텍스트를 활용할 수 있다'고 조언했다.
- 184유로 VM 비용에 대한 흥미로운 시각도 있었다. '3주 인건비를 쏟은 프로젝트에서 184유로는 그냥 잔돈'이라는 댓글이 많은 공감을 얻었다. 또한 'SQLite처럼 백엔드 없이 파일 하나로 작동하는 RAG 도구는 없냐'는 질문도 나왔는데, 이는 많은 개발자들이 간단한 RAG 솔루션을 원한다는 것을 보여준다.
How to Apply
- 사내 문서 기반 RAG를 처음 구축한다면, 임베딩 모델 선택보다 데이터 필터링 파이프라인을 먼저 만들어라. mp4, exe, zip, 백업 파일, 시뮬레이션 결과 파일 등 텍스트 추출이 불가능하거나 의미 없는 파일을 확장자/파일명 패턴으로 걸러내는 작업만 해도 메모리 폭발과 파이프라인 중단 문제를 상당 부분 예방할 수 있다.
- 로컬 LLM 기반 RAG를 빠르게 프로토타이핑하려면 Ollama + LlamaIndex + nomic-embed-text 조합을 시작점으로 고려할 수 있다. 이 스택은 적은 코드로 동작하는 프로토타입을 만들기 좋으나, 실제 데이터를 투입하기 전에 파일 크기 상한선 설정과 예외 처리를 반드시 추가해야 한다.
- 인덱싱 작업이 수 주 이상 걸리는 대규모 문서라면, 노트북 대신 Hetzner 같은 클라우드 VM에서 처리하는 것을 처음부터 계획하라. 인건비 대비 VM 비용은 미미하고, 중단 없이 장시간 실행할 수 있어 훨씬 안정적이다.
- 검색 품질을 높이고 싶다면 임베딩 모델 교체보다 재랭킹(Re-ranking) 단계를 파이프라인에 추가하는 것이 더 효과적일 수 있다. 벡터 검색으로 Top-K 후보를 뽑은 뒤, 재랭커가 실제 질문과의 관련도를 다시 점수 매기는 방식으로, 임베딩 모델은 오히려 작고 저렴한 것을 써도 된다.
Terminology
RAGRetrieval-Augmented Generation의 약자. LLM이 답변을 생성할 때 미리 인덱싱해둔 문서에서 관련 내용을 검색해 참고하게 하는 방식. 마치 시험 볼 때 오픈북으로 관련 페이지를 찾아보는 것과 비슷하다.
임베딩(Embedding)텍스트를 숫자 벡터로 변환하는 과정. 의미가 비슷한 문장은 벡터 공간에서 가까운 위치에 놓여, 유사도 검색이 가능해진다.
청킹(Chunking)긴 문서를 검색에 적합한 크기의 조각으로 나누는 작업. 너무 크면 노이즈가 섞이고, 너무 작으면 맥락이 끊기는 트레이드오프가 있다.
재랭킹(Re-ranking)벡터 검색으로 1차 후보 문서를 뽑은 뒤, 별도 모델이 질문과의 실제 관련도를 다시 점수 매겨 순서를 재정렬하는 과정. 검색 정확도를 높이는 데 효과적이다.
nomic-embed-textNomic AI가 만든 오픈소스 텍스트 임베딩 모델. 로컬에서 실행 가능하고 기술 문서에서 품질이 좋은 것으로 알려져 있다.
LlamaIndex문서 로딩, 청킹, 임베딩 생성, 벡터 DB 저장, 쿼리를 하나의 파이프라인으로 묶어주는 Python 기반 RAG 오케스트레이션 프레임워크.