3. Modular RAG
3.1 Modular RAG란 무엇인가요?
Modular RAG는 RAG 시스템을 여러 개의 독립적인 모듈로 나눠서 구성하는 방식입니다. 핵심은 “RAG를 파이프라인이 아니라 시스템으로 보기 시작한다”는 것입니다.
Naive RAG나 Advanced RAG를 생각해보면, 처음부터 끝까지 하나의 흐름으로 연결되어 있습니다. 질문이 들어오면 → 쿼리 처리 → 검색 → 리랭킹 → 생성 → 답변 출력. 이 모든 단계가 하나의 코드, 하나의 프로세스로 묶여 있습니다.
이렇게 하나로 묶여 있으면 처음에는 간단해 보이지만, 시스템이 커지면 여러 문제가 생깁니다. 검색 엔진만 바꾸고 싶어도 전체 코드를 수정해야 합니다. 한 부분에서 버그가 나면 어디가 문제인지 찾기 어렵습니다. 여러 명이 동시에 작업하기 힘듭니다.
Modular RAG는 이 흐름을 독립적인 모듈들로 분리합니다. Retriever(검색기), Ranker(순위 조정기), Generator(생성기), Evaluator(평가기) 등이 각각 독립적인 컴포넌트로 존재하고, 이들을 조합해서 전체 시스템을 구성합니다. 마치 레고 블록처럼 각 부품을 따로 만들어서 필요에 따라 조합하는 것입니다.
3.2 왜 모듈로 나누나요?
모듈로 나누는 이유를 구체적인 상황과 함께 설명하겠습니다.
이유 1: 교체와 확장이 쉬워집니다.
회사에서 RAG 시스템을 만들었는데, 처음에는 ChromaDB를 벡터 저장소로 사용했습니다. 그런데 사용자가 늘어나면서 ChromaDB로는 성능이 부족해졌습니다. Modular RAG로 구현했다면 벡터 저장소 모듈만 Pinecone이나 Weaviate로 교체하면 됩니다. 나머지 모듈(쿼리 처리, 리랭킹, 생성 등)은 전혀 건드릴 필요가 없습니다.
만약 모듈화 없이 구현했다면? 코드 곳곳에 ChromaDB 관련 코드가 흩어져 있을 것이고, 이걸 모두 찾아서 수정해야 합니다. 수정하다가 다른 부분을 건드릴 위험도 있습니다.
이유 2: 팀 협업이 쉬워집니다.
RAG 시스템을 팀에서 함께 개발한다고 가정해봅시다. 모듈화 없이 개발하면 모든 팀원이 같은 코드를 건드려야 하고, 충돌이 자주 발생합니다. 모듈화하면 “김철수는 검색 모듈 담당, 이영희는 생성 모듈 담당, 박민수는 평가 모듈 담당”처럼 역할을 나눌 수 있습니다. 각자 맡은 모듈만 집중해서 개발하고, 나중에 조합하면 됩니다.
이유 3: 테스트와 디버깅이 쉬워집니다.
시스템에서 문제가 발생했을 때, 모듈화되어 있으면 “검색 모듈의 출력은 정상인데, 리랭킹 모듈에서 이상한 결과가 나오네”처럼 문제의 원인을 빠르게 좁힐 수 있습니다. 각 모듈을 독립적으로 테스트할 수도 있습니다.
이유 4: 재사용이 가능합니다.
한 번 잘 만든 임베딩 모듈은 다른 프로젝트에서도 그대로 사용할 수 있습니다. 사내 문서 검색 시스템에서 사용한 검색 모듈을 고객 서비스 챗봇에서도 재사용할 수 있습니다.
3.3 Modular RAG의 주요 모듈들
Modular RAG에서 흔히 사용되는 모듈들을 설명하겠습니다. 각 모듈이 어떤 역할을 하고, 왜 독립적으로 분리되어야 하는지 이해하는 것이 중요합니다.
문서 로더(Document Loader) 모듈은 다양한 형식의 문서를 읽어오는 역할을 합니다. PDF 파일, Word 문서, 웹 페이지, 데이터베이스, API 응답 등 여러 소스에서 텍스트를 추출합니다. 이 모듈을 분리하면, 새로운 문서 형식(예: 특수한 사내 문서 포맷)을 지원하고 싶을 때 이 모듈만 확장하면 됩니다.
텍스트 분할(Text Splitter/Chunker) 모듈은 긴 문서를 적절한 크기의 조각으로 나누는 역할을 합니다. 고정 크기로 나누기, 문장 단위로 나누기, 의미 단위로 나누기 등 다양한 전략을 선택할 수 있습니다. 문서의 특성에 따라 다른 분할 전략이 필요할 수 있으므로 독립 모듈로 분리합니다.
임베딩(Embedding) 모듈은 텍스트를 벡터로 변환하는 역할을 합니다. 다양한 임베딩 모델 중에서 선택할 수 있습니다. 한국어에 특화된 모델, 영어에 최적화된 모델, 다국어 모델, 특정 도메인(의학, 법률 등)에 특화된 모델 등 용도에 맞는 모델을 쉽게 교체할 수 있습니다.
벡터 저장소(Vector Store) 모듈은 임베딩을 저장하고 검색하는 역할을 합니다. ChromaDB, Pinecone, Weaviate, Milvus, FAISS 등 다양한 벡터 데이터베이스를 지원합니다. 프로젝트 규모나 요구사항(온프레미스 vs 클라우드, 비용 vs 성능)에 따라 다른 데이터베이스로 쉽게 전환할 수 있습니다.
검색기(Retriever) 모듈은 질문과 관련된 문서를 찾아오는 역할을 합니다. 단순 벡터 검색, 하이브리드 검색, 필터링이 포함된 검색, 메타데이터 기반 검색 등 다양한 검색 전략을 구현할 수 있습니다.
순위 조정기(Ranker/Reranker) 모듈은 검색 결과의 순서를 재조정하는 역할을 합니다. 간단한 키워드 매칭부터 복잡한 Cross-encoder 모델까지 다양한 리랭킹 방법을 선택할 수 있습니다.
생성기(Generator) 모듈은 최종 답변을 생성하는 역할을 합니다. OpenAI GPT, Anthropic Claude, Google Gemini, Ollama의 로컬 모델 등 다양한 LLM을 지원합니다. 비용이나 성능, 보안 요구사항에 따라 모델을 쉽게 교체할 수 있습니다.
평가기(Evaluator) 모듈은 검색 결과나 생성된 답변의 품질을 평가하는 역할을 합니다. 이 모듈은 Corrective RAG나 Self-RAG에서 특히 중요합니다.
3.4 Modular RAG가 MLOps/LLMOps로 넘어가는 다리인 이유
Modular RAG는 단순히 코드 정리 방법이 아니라, 프로덕션 레벨의 시스템 운영으로 넘어가는 다리입니다.
실제 서비스에서 RAG를 운영하려면 다음과 같은 것들이 필요합니다:
- 각 모듈의 성능을 모니터링하고 병목을 찾아야 합니다. (검색이 느린지? 생성이 느린지?)
- 모듈별로 다른 버전을 배포하고 A/B 테스트를 해야 합니다. (새 리랭킹 모델이 더 좋은지?)
- 문제가 발생하면 특정 모듈만 롤백해야 합니다.
- 트래픽에 따라 특정 모듈만 스케일업해야 합니다. (검색 요청이 많으면 검색 모듈만 증설)
이런 것들은 시스템이 모듈화되어 있지 않으면 불가능하거나 매우 어렵습니다. Modular RAG 구조를 갖추면 MLOps/LLMOps의 다양한 도구와 방법론을 적용할 수 있게 됩니다.
3.5 Modular RAG의 단점
물론 Modular RAG에도 단점이 있습니다.
첫째, 초기 설계에 더 많은 노력이 필요합니다. 모듈 간의 인터페이스를 어떻게 정의할지, 데이터를 어떤 형식으로 주고받을지 미리 계획해야 합니다. 처음에 설계를 잘못하면 나중에 전체를 다시 만들어야 할 수도 있습니다.
둘째, 작은 프로젝트에서는 오버엔지니어링이 될 수 있습니다. 간단한 프로토타입이나 개인 프로젝트에서 굳이 Modular RAG 구조를 갖출 필요는 없습니다. 오히려 복잡성만 증가합니다.
셋째, 모듈 간의 의존성 관리가 필요합니다. 어떤 모듈이 어떤 모듈에 의존하는지, 버전 호환성은 어떤지 관리해야 합니다.
3.6 Modular RAG는 언제 사용하면 좋을까요?
Modular RAG는 다음과 같은 경우에 적합합니다:
- 여러 명이 함께 개발하는 팀 프로젝트
- 장기적으로 유지보수하고 발전시켜야 하는 시스템
- 요구사항이 자주 바뀌거나, 여러 가지 구성을 실험해봐야 하는 경우
- 프로덕션 환경에서 운영해야 하는 서비스
반면, 빠른 프로토타입이나 개인 학습 목적이라면 Naive RAG나 Advanced RAG를 단일 스크립트로 구현하는 것이 더 효율적입니다.