본문 바로가기

개발 자동화 & 생산성 도구

5편 사내 RAG + 자동화 시스템 운영 전략 — 안정성·정확도·속도를 모두 잡는 실무 운영법

반응형

 

🟦 개발 생산성 & 자동화 시리즈 — 5편

사내 RAG + 자동화 시스템 운영 전략 — 안정성·정확도·속도를 모두 잡는 실무 운영법

RAG 기반 문서 검색/요약 시스템을 구축한 뒤 진짜 중요한 건 운영이다.
초기 PoC 단계에서는 잘 돌아가던 시스템도, 문서가 수십만 건으로 늘어나거나
사용자가 많아지면 문제들이 터지기 시작한다.

이 글에서는 *“사내 자동화 RAG 시스템을 어떻게 안정적으로 운영할 것인가”*를
실제 구축·운영 경험 기반으로 정리했다:

  • 임베딩 성능 튜닝
  • 벡터DB 운영 전략
  • 문서 변경/추가 시 자동 파이프라인
  • LLM 비용/속도 최적화
  • 보안/접근권한/로그 정책
  • 검색 정확도 유지 방법

모두 실무에서 바로 참고할 수 있도록 설계했다.


🟦 1. 운영 환경에서 발생하는 진짜 문제들

초기 PoC에서는 “어? 생각보다 잘 되는데?” 하다가
실제로 운영 단계에 진입하면 갑자기 아래 문제들이 나타난다.

❌ 1) 문서가 많아지면 검색 속도가 기하급수적으로 느려짐

특히 벡터DB를 잘못 구성하면 검색 시간이 1~2초 → 10초 이상으로 뻥튀기.

❌ 2) 매일 신규 문서가 추가되면서 인덱스가 지저분해짐

문서 변경/수정/삭제가 잦으면 중복 문서가 계속 축적된다.

❌ 3) 문서 내용이 갱신되었는데도 오래된 임베딩이 그대로 남음

RAG 정확도 급락.

❌ 4) LLM 사용량 증가로 compute 비용 폭증

특히 “요약 자동화”가 회사 전체로 퍼지면 LLM 비용이 몇 배로 튀기 쉽다.

❌ 5) RAG 답변이 문서와 다르게 나오는 현상(할루시네이션) 재발

특히 업무 문서가 업데이트되었을 때 문제 발생.

❌ 6) 보안/접근 권한 문제

내부 문서별 ACL(Access Control)까지 통합하는 건 더 어려운 문제다.

이제 하나씩 어떻게 해결했는지 설명한다.


🟦 2. 전체 운영 아키텍처 — 실전 구성

운영 단계에서는 단순 RAG가 아니라 자동화 파이프라인 + 모니터링 + 버저닝이 필요하다.

아키텍처는 이렇게 정리됐다.

[문서 감시] 
  → [증분 수집] 
    → [문서 변환] 
      → [임시 저장]
        → [청킹 / 요약]
          → [임베딩 생성]
            → [벡터DB 버저닝 저장]
              → [검색 API]
                → [LLM Filtering / Answering]
                  → [모니터링 / 품질지표 관리]

핵심은 증분 인덱싱(Incremental Indexing)버저닝(Vector Versioning) 이다.


🟦 3. 문서 자동 인덱싱 — 완전 자동화를 설계하는 방법

🔵 1) 문서 변경 감지(Watchdog 기반)

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class Handler(FileSystemEventHandler):
    def on_modified(self, event):
        process_file(event.src_path)

observer = Observer()
observer.schedule(Handler(), path="/shared/docs", recursive=True)
observer.start()

문서가 추가/수정되면 자동으로 변환 → 임베딩까지 이어지는 구조.


🔵 2) 문서 해시 기반 중복 제거

문서별 SHA256 해시를 기록해두면
문서가 수정되었는지 여부를 금방 판단할 수 있다.

import hashlib

def filehash(path):
    with open(path,'rb') as f:
        return hashlib.sha256(f.read()).hexdigest()
  • 해시가 변경되면 기존 인덱스를 폐기
  • 변경 없으면 재인덱싱 생략

이게 시스템 부하를 90% 줄여준다.


🟦 4. Chunking & Embedding — 운영에서 가장 중요한 단계

운영 단계에서 chunking 전략이 잘못되면
문서 수가 늘어날수록 정확도가 급격히 떨어진다.

실제 운영에서 가장 성능이 좋았던 규칙:

  • 문단 중심 chunking
  • 600~900 토큰
  • 100~200 overlap
  • 표/목차/코드블록은 별도 chunk

코드 예시는 다음과 같다.

splitter = RecursiveCharacterTextSplitter(
    chunk_size=850,
    chunk_overlap=150,
    separators=["\n\n", "\n", ".", " "]
)

문서 유형별로 chunk 규칙을 다르게 적용하는 것도 큰 효과가 있었다:

  • 제안서: 문단 중심
  • API 문서: 문장 중심
  • 회계/수치 문서: 표 중심
  • 회의록: 시간순 chunk

🟦 5. Vector DB 운영 전략 — 속도·정확도·비용 모두 잡기

🔵 1) Hybrid Search 구조

벡터 검색 + 키워드 검색을 함께 사용하는 방식이
정확도 향상에 매우 효과적이다.

  • BM25
  • Sparse Embedding(bge-m3에서 제공)
  • Dense Embedding 결합

Qdrant 기준:

HNSW + BM25 Hybrid Mode

🔵 2) 벡터DB 샤딩/압축

문서가 50,000건 → 300,000건으로 늘어가면서
Qdrant 파티션을 나눴다.

  • 문서 유형별 컬렉션 분리
  • 스토리지 비용 절약 위해 float16 압축
  • Rerank는 상위 20개까지만 적용

🔵 3) Vector Versioning 도입

문서 변경 시 기존 인덱스를 바로 삭제하지 않고
버전 1, 2, 3 형태로 보관했다.

이유는:

  • 신규 임베딩이 품질이 더 떨어질 가능성
  • 회귀 테스트가 지원되어야 함
  • 과거 문서 인용 시 참고 필요

버전별 엔트리 수가 너무 늘어나면
7일 단위로 자동 만료 처리.


🟦 6. LLM 비용 및 성능 최적화 전략

🔵 1) 요약은 2단계로 나누고 batch 처리

문서가 많아질수록 요약이 가장 큰 비용을 만든다.

  • Chunk Summary → Global Summary
  • 요약 요청을 배치로 묶어 처리
  • vLLM 로컬 모델 우선 사용
  • 대형 모델은 최종 검증 단계에만 사용

🔵 2) 사내 vLLM + KV 캐시 최적화

vLLM을 장기 운영하면 다음이 필수다.

  • tensor_parallel_size 2~4
  • gpu_memory_utilization 0.9
  • KV 캐시 사이즈 늘리기
  • 배치 사이즈 점진적 증가

결과적으로 API 응답속도가 2~4배 빨라졌다.


🟦 7. 검색 정확도 모니터링 — 운영에서 가장 중요한 지표

RAG 시스템은 운영하면서 정확도가 떨어지는 현상이 반복된다.
그래서 아래 지표들을 지속적으로 모니터링했다.

🔵 모니터링 지표

지표 의미

Retrieval Hit Rate 찾은 문서가 실제 정답 문서와 일치
Rerank Precision 상위 Top-k의 품질
Answer Grounding Score 답변이 문서 기반인지 여부
Hallucination Rate 문서에 없는 내용이 등장하는 비율
Average Response Time 검색/답변 시간
Chunk Coverage 전체 문서 대비 참조된 chunk 비율

정확도 하락이 보이면 다음을 점검했다:

  • chunk 규칙 재조정
  • embedding 모델 변경(nomic → bge-m3)
  • BM25 weight 조정
  • Rerank 모델 교체

🟦 8. 사내 보안/ACL 연동 전략

사내 문서는 권한이 가장 중요하다.

적용한 구조:

  • 문서별 ACL을 메타데이터로 저장
  • 사용자 토큰 → ACL 매핑
  • 검색 결과에서 ACL 안 맞는 chunk 제거
  • 허가되지 않은 문서 chunk는 rerank 대상에서도 제외

다음과 같이 구현했다:

def filter_acl(results, user_roles):
    return [r for r in results if r.payload["acl"] in user_roles]

문서가 섞여 있는 대규모 RAG 시스템이라면 필수 기능이다.


🟦 9. 실전 팁 3개

① Chunk 정책이 고정되면 안 된다 — 문서 유형별로 다르게 가져가라

운영 환경에서는 문서 유형이 너무 다양해
한 가지 chunk 정책으로는 정확도가 유지되지 않는다.

문서 유형별로 chunking 전략을 따로 만드는 것이 핵심.


② 대부분의 문제는 “Embedding 품질”에서 발생한다

운영 중 정확도 떨어지면 80%는 embedding 문제였다.

  • bge-m3
  • bge-large-en
  • nomic-embed

모델을 교체하는 것만으로도 정확도가 대폭 올라간다.


③ LLM 비용은 반드시 로컬 vLLM + Batch로 해결하라

문서 요약은 무조건 비용 지옥으로 간다.
배치 처리 + 로컬 LLM로 옮겨오는 순간 비용이 70~90% 감소한다.


🟦 추천 태그

#RAG #문서검색 #사내AI #업무자동화 #개발자동화 #Embedding #Docling  
#vLLM #FastAPI #벡터DB #Qdrant #Milvus #OCR #LLM운영 #AI시스템구축기

 

반응형