본 시스템은 Rails API를 중심으로 Vectra 클라이언트, 자가 호스팅 Qdrant 벡터 데이터베이스, Sidekiq 기반 백그라운드 작업 처리, 그리고 자가 호스팅 Sentence-Transformers 임베딩 생성 서비스를 포함하는 고수준 아키텍처를 채택했습니다.
멀티테넌트 문서 처리 파이프라인
-
문서 모델:
Document모델은tenant_id를 통해 테넌트 소유권을 명확히 하고,statusenum으로 처리 상태를 추적하며,document_chunks를 통해 분할된 청크를 관리합니다.after_create콜백으로DocumentProcessingJob을 스케줄링하여 업로드 속도를 최적화합니다. -
청크 분할 전략: 300페이지 분량의 PDF 문서를 효율적으로 처리하기 위해 슬라이딩 윈도우 방식과 128 토큰의 오버랩을 적용하여 문맥 연속성을 확보했습니다. 이는
pdf-reader젬을 활용하여 텍스트를 추출하고 토큰화하여 구현됩니다. -
백그라운드 처리:
DocumentProcessingJob은 Sidekiq을 통해 실행되며, 문서 분할, 임베딩 생성, 벡터 DB 색인, 상태 업데이트, 감사 로그 기록 등의 단계를 비동기적으로 처리합니다. 오류 발생 시 지수 백오프 방식의 재시도 로직을 포함합니다. -
자가 호스팅 임베딩 서비스: GDPR 준수를 위해 클라이언트 데이터를 외부 서비스로 전송하지 않고,
Faraday를 사용하여 자체 호스팅된all-mpnet-base-v2모델을 통해 임베딩을 생성합니다. 이는 OpenAI API 대비 월 200달러의 비용 절감 효과를 가져옵니다.
벡터 검색 및 멀티테넌트 격리
-
데이터 격리: Qdrant의 네임스페이스 기능을 활용하여 테넌트별 데이터 격리를 구현하며,
VectorIndexingService내에서tenant_id를 기반으로 네임스페이스를 생성합니다. -
“Never Trust, Always Verify”: 검색 결과에 대해 Qdrant 네임스페이스만 신뢰하지 않고, 애플리케이션 레벨에서 반환된 메타데이터의
tenant_id를 재확인하여 잠재적인 보안 위협을 즉시 감지하고 경고하는 방어적 깊이(defense in depth) 전략을 적용합니다. -
클라이언트 및 캐싱:
Vectra.qdrant클라이언트를 사용하여 Qdrant에 연결하며, 검색 결과의 TTL(Time-To-Live)을 1시간으로 설정한 캐싱 레이어를 적용하여 성능을 최적화합니다.
엔터프라이즈 검색 API
-
SearchController는 사용자 인증 및 속도 제한(rate_limit_check- 사용자당 시간당 100회)을 적용합니다. -
쿼리 유효성 검사, 필터링, 벡터 검색 수행, 결과 하이드레이션(Document 모델 로드 및 검색 점수/청크/페이지 정보 주입), 검색 및 감사 로그 기록 등의 기능을 제공합니다.
-
Vectra::Error발생 시 Sentry를 통해 예외를 기록하고, SQL 검색으로 대체하는 우아한 오류 처리(graceful fallback)를 구현하여 시스템 가용성을 높입니다.