메타데이터 필터는 벡터 유사도 검색에 tenant_id, 문서 유형, 발행일 같은 조건을 더하는 장치다. 이번 실험에서는 "필터를 어디에 넣어야 recall과 지연시간이 동시에 괜찮은가"를 검증했다.

메타데이터 필터는 문서 QA recall을 실제로 올리는가?

결론부터 적으면, 올릴 수는 있지만 "어떻게 넣었는가"에 전적으로 달려 있다. 필터를 검색 뒤에 거는 post-filtering은 조건을 만족하는 문서가 적을수록(선택도가 낮을수록) top-k가 비어버릴 위험이 커지고, 검색 전·검색 중에 거는 pre/in-algorithm filtering은 인덱스 구조를 더 복잡하게 만든다. 2026년 기준 공개 벤치마크들은 이 트레이드오프를 선택도 구간별로 나눠 측정하고 있고, 이번 실험도 그 구간을 그대로 재현했다.

핵심 정리

  • 필터 선택도는 recall·QPS와 함께 반드시 별도 변수로 측정해야 한다. 선택도를 고정하지 않은 비교는 재현이 어렵다.
  • post-filtering은 선택도가 낮을 때(예: 1%) 후보를 충분히 늘리지 않으면 반환 결과가 k보다 적어진다.
  • in-algorithm filtering 제품은 10% 선택도에서 필터 없는 검색보다 오히려 처리량이 높은 경우도 보고됐다.
  • 필터 추출 정확도와 최종 QA 정확도는 별도 지표로 쪼개야 원인을 찾을 수 있다.
  • 공개 수치는 특정 제품·버전·하드웨어 조건의 결과이므로 그대로 재현된다고 가정하면 안 된다.

실험 설계는 단순했다. 사내 문서 더미셋(정책 문서, 버전이 다른 가이드, 권한 등급이 섞인 자료)을 chunk 단위로 쪼개고, tenant_id, document_type, published_at, effective_from/to, access_level을 필터 필드로 걸었다. 그리고 "이 질문에 대해 조건을 만족하는 문서 중 top-k를 제대로 반환하는가"만 검증 대상으로 좁혔다.

필터를 어느 단계에 넣어야 하는가 — 검색 전인가, 후인가, 인덱스 안인가?

결론은 세 가지 구성(Dense-only, Dense 검색 후 post-filter, pre/in-algorithm filter + Dense)을 나란히 돌려보지 않으면 "필터가 품질을 올렸는지"조차 판단할 수 없다는 것이다. post-filtering은 구현이 가장 쉬웠지만, 전체 벡터 중 특정 tenant가 1%만 차지하는 조건에서는 원하는 k개를 채우기 위해 후보를 훨씬 더 넓게 뽑아야 했다. 그렇지 않으면 반환 결과 수가 k보다 적거나 관련 문서가 누락됐다 출처.

반면 in-algorithm filtering 계열 제품은 상황이 달랐다. 2025년 비교 실험에서는 Pinecone-p2와 Zilliz AUTOINDEX가 10% 선택도 필터에서 필터 없는 검색보다 처리량이 약 1.2~1.5배 높게 나온 반면, LanceDB IVF_PQ, OpenSearch HNSW, pgvector HNSW 계열은 필터를 걸면 QPS가 떨어졌다고 보고됐다 출처. 같은 "메타데이터 필터"라는 말이 제품마다 완전히 다른 성능 곡선을 의미할 수 있다는 걸 이 지점에서 확인했다.

선택도가 99%를 넘으면 무슨 일이 생기는가?

이 구간에서는 질의 속도와 recall이 동시에 불안정해진다. VDBBench 1.0은 메타데이터 조건이 전체 벡터의 50~99.9%를 제외하도록 구성해 필터 성능을 측정했고, 99% 이상을 제거하는 고선택도 구간에서는 질의 속도가 여러 자릿수로 변동할 수 있다고 보고했다 출처.

이번 실험에서도 전체 chunk의 50%, 10%, 1%, 0.1%만 남는 필터와 0건 필터를 회귀 세트에 넣어 같은 조건(동일 임베딩 모델, 동일 top-k, 동일 동시 요청 수)으로 돌렸다. 0.1% 구간에서는 반환 결과 수가 요청한 k보다 작게 나오는 경우가 반복됐고, 그 원인이 "후보 확장 부족"인지 "필터 추출 오류"인지 나눠 보지 않으면 디버깅이 되지 않았다.

참고할 만한 실측 조건은 다음과 같다. Pinecone 사례는 120만 개 벡터, 768차원 조건에서 측정됐고, 필터 없음 평균 지연시간 79ms, 50% 선택 필터 57ms, 1% 선택 필터 51.6ms로 보고됐다. 16개 검색 스레드 기준 Pinecone은 필터 없음 약 800 QPS, 10% 필터 약 600 QPS였고, Zilliz AUTOINDEX는 각각 약 750 QPS, 700 QPS였다. P95 지연시간은 통합 필터링 시스템에서 대체로 30~50ms 수준으로 보고됐다 출처. 이 수치는 특정 인덱스·하드웨어·동시성 조건의 결과이므로 그대로 일반화할 수는 없다.

필터 스키마와 추출 프롬프트는 어떻게 고정했는가?

스키마를 처음부터 고정하지 않으면 회귀 테스트 자체가 불가능했다. 사용한 필드는 document_id, chunk_id, tenant_id, source, document_type, title, section, language, published_at, effective_from, effective_to, version, access_level이다. 날짜·버전·권한을 문자열 하나로 뭉치지 않고 비교 가능한 원자 필드로 저장해야 범위 필터(effective_from <= 기준일 AND effective_to >= 기준일)와 회귀 테스트가 가능했다. 2026년 정리된 Meta-RAG 사례도 제목, 회사명, 키워드, 요약, 날짜, 보고서 유형을 메타데이터 핵심 필드로 사용했다 출처.

청킹 단계에서는 원문 식별자, 문서 유형, 발행일, 권한 범위를 모든 chunk에 복사하고 page, section, heading_path를 추가로 기록했다. 그래야 검색 결과를 원문으로 복원하거나 같은 문서의 인접 chunk를 재검색할 수 있었다.

자연어 질문에서 필터를 뽑는 프롬프트는 답변이 아니라 구조화된 JSON으로 제한했다.

질문에서 문서 검색 제약조건만 추출하라.
추측하거나 누락된 값을 임의로 채우지 말라.

출력 스키마:
{
  "tenant_id": null,
  "document_type": null,
  "language": null,
  "date_from": null,
  "date_to": null,
  "version": null,
  "access_level": null,
  "unresolved_constraints": []
}

이 출력은 바로 필터로 넘기지 않고, 필터 필드 정확도·필터 값 정확도·필터 누락률·과잉 필터율을 따로 집계했다. Meta-RAG 사례에서는 메타데이터를 쓰지 않은 FinanceBench Hit@1이 0.53에서 메타데이터를 쓴 뒤 0.65로 올랐다고 보고됐지만, 이 수치는 특정 파이프라인과 데이터셋의 결과이며 일반적인 개선률로 보기는 어렵다 출처.

무엇을 측정했고, 어디서 막혔는가?

세 구성을 나란히 돌려 비교했을 때 가장 먼저 드러난 건 "필터 위반률 0건"이 생각보다 어렵다는 점이었다. tenant_id = A를 지정했는데 B의 문서가 섞이는지, effective_date 조건을 어기는 문서가 반환되는지를 매 구성마다 확인해야 했다.

구성 필터 위반률 빈 결과율 비고
Dense-only 측정 불가(필터 자체 없음) 0% baseline
Dense + post-filter 선택도 1% 이하에서 증가 선택도 0.1%에서 반복 발생 후보 확장량에 민감
pre/in-algorithm filter + Dense 가장 낮음 가장 낮음 인덱스 복잡도·메모리 증가

비용은 벡터 저장량만으로 계산할 수 없었다. 메타데이터 필드 수, 색인 여부, 인덱스 메모리, 필터 전용 인덱스, reranking 후보 수, 동시성, 원문 저장·복원 비용을 분리해야 했다. pre-filtering은 검색 정확도와 예측 가능성을 높일 수 있었지만 메타데이터를 인덱스 구조에 반영해야 하므로 복잡도와 메모리 비용이 함께 늘었다 출처.

한계도 분명했다. 이번 실험에서 참고한 공개 수치는 Pinecone YFCC·고객 데이터, VDBBench 워크로드, 특정 벡터 엔진·설정에 기반한다. YFCC 데이터셋에서 mean recall@10이 0.989, 내부 검색 지연시간 약 20ms로 보고된 연구도 있지만 출처, 우리가 쓰는 엔진·버전·인덱스 방식·하드웨어가 다르면 같은 수치는 재현되지 않았다. 특히 고선택도(0.1% 이하) 구간은 우리 환경에서 자체 측정치가 아직 안정적이지 않아, 이 글의 결론은 "방향성 확인"에서 멈춘다.

이번 실험에서 남은 것은?

세 구성을 나란히 비교하지 않았다면 "필터가 품질을 올렸다"는 말이 어느 구성을 가리키는지조차 알 수 없었을 것이다. 다음 실험에서는 필터 전용 인덱스를 별도로 두었을 때의 메모리 비용과, 0.1% 이하 초고선택도 구간의 자체 재현치를 더 쌓는 쪽으로 넘어갈 계획이다. 지금 단계에서는 "필터를 걸면 좋아진다"가 아니라 "필터를 어느 단계에, 어떤 선택도로 걸었는지를 기록해야 비교가 가능하다"는 것이 가장 확실한 결론이다.

핵심 정리

  • 필터 선택도(50%~0.1%, 0건 포함)를 고정된 회귀 세트로 만들어야 실험이 재현 가능하다.
  • post-filtering은 저선택도에서 후보 확장이 부족하면 결과 누락이 생기고, pre/in-algorithm filtering은 메모리·복잡도 비용이 올라간다.
  • 필터 위반률·빈 결과율·Recall@k·P95를 각각 따로 집계해야 원인을 분리할 수 있다.
  • 공개 벤치마크 수치(VDBBench, Pinecone, Meta-RAG)는 참고 방향일 뿐, 자체 엔진·데이터로 재현해야 신뢰할 수 있다.