개념
verified · type: concept · verified: 2026-07 · review: 180d · updated: 2026-08-09 · [concept]

임베딩과 벡터 검색

RAG 를 붙이기 전에 "임베딩 모델 뭐 쓰고, 벡터DB 를 정말 세워야 하나, 하이브리드/리랭킹이 필요한가" 를 결정할 때 연다.


그림 — 임베딩 — 뜻이 가까우면 거리도 가깝다
고양이 냥이 강아지 부가세 신고 연말정산 ← 거리 = 의미 차이 →
문장을 수백 차원의 좌표로 바꾸면 "비슷한 뜻 = 가까운 점"이 된다. 검색은 질문의 좌표에서 가장 가까운 점들을 줍는 일이다.

결론부터: 대부분 pgvector 로 충분하다

검색 품질을 결정하는 건 벡터DB 가 아니라 임베딩 모델이다. DB 를 pgvector 에서 Pinecone 으로 바꿔도 임베딩이 도메인 의미를 못 잡으면 소용없다. 순서는 (1) 좋은 임베딩 → (2) 하이브리드+리랭킹 → (3) 그래도 규모가 문제면 전용 벡터DB 다.

벡터DB 를 따로 세워야 하는 건 수백만 벡터 + 저지연이 동시에 필요할 때뿐이다. 10만 벡터 미만이면 brute-force NumPy 로도 충분하고, 이미 Postgres 를 쓰면 pgvector 하나로 정형 데이터와 벡터를 한 트랜잭션에 둘 수 있다. [MED]

임베딩 모델 고르기 (차원·다국어·비용)

기준 실무 판단
범용 텍스트 OpenAI / Cohere 같은 범용 모델이 대부분 잘 맞는다 [MED]
특수 도메인(의료·법률·코드) fine-tune 된 도메인 모델이 범용보다 낫다 [MED]
차원 흔히 1024~1536. 크다고 항상 낫지 않고 저장·검색 비용만 는다 [MED]
다국어 한국어 등 비영어는 다국어 학습 모델을 명시적으로 골라라 (재확인 필요)
비용 차원↓ = 저장·검색 비용↓. Matryoshka 로 잘라 조절
  • OpenAI text-embedding-3-large = 기본 3072차원, Matryoshka 로 256/1024 로 truncate 가능. text-embedding-3-small = 1536차원, throughput 최적화. (verified 2026-07) [MED]
  • Matryoshka Representation Learning = 앞쪽 차원에 정보를 몰아넣어 벡터를 잘라도 성능이 유지되게 학습하는 기법. 저장·검색 비용을 줄이는 레버. text-embedding-3-large 를 256차원으로 줄여도 구형 ada-002 의 1536차원보다 낫다고 발표됐다. [MED]

정규화와 유사도 지표

  • 정규화(L2 norm)된 벡터에서는 코사인 유사도와 내적(dot product)이 랭킹상 동일하다. 내적이 곱·합만 해서 더 빠르다. OpenAI 임베딩은 이미 정규화되어 나오므로 유클리드·코사인 랭킹이 같다. [HIGH]
  • 대부분 벡터DB(FAISS, Pinecone, Weaviate, Milvus)는 코사인을 "한 번 정규화 후 내적"으로 구현한다. [MED]
  • 정규화가 항상 옳은 건 아니다. 추천 시스템처럼 magnitude 가 인기도·판매량을 인코딩하면 정규화가 정보를 지운다. 규칙: 임베딩 모델이 학습 때 쓴 지표에 맞춰라. [HIGH]

벡터DB 선택표

상황 선택
이미 Postgres 유저, ~수백만 이하 pgvector (기본 추천)
인프라 운영을 피하고 싶다 Pinecone (완전관리형)
프로토타입·중소 규모, DX 우선 Chroma
성능 크리티컬 Qdrant (Rust)
수십억 벡터·클러스터 Milvus
의미 + 정형 스키마 Weaviate (GraphQL)
  • 인덱스: HNSW = 검색 O(log N), recall·속도 우수하나 그래프를 전부 메모리에 유지(지연 민감·중간 규모). IVF = 클러스터만 탐색, 메모리 적고 대규모에 유리(같은 속도면 recall 낮음). PQ = 100~1000배 압축, 정확도 손실(IVF 와 결합). [MED]
  • recall 목표는 90~95%. 95% 를 넘기려 하면 수확체감이다. [MED]

하이브리드 검색과 리랭킹이 왜 필요한가

순수 벡터 검색은 exact-match 에 약하다. BM25(sparse) 는 기술 용어·식별자·코드·인용 문자열처럼 벡터가 놓치는 정확 일치를 잡는다. BM25 없는 RAG 는 체계적 사각지대를 갖는다. [MED]

파이프라인: BM25 + 벡터를 병렬 실행 → RRF 로 융합 → (선택) cross-encoder 리랭크 → top-K 를 LLM 에 전달.

  • RRF(Reciprocal Rank Fusion): score(d) += 1 / (k + rank(d)), rank 는 1부터. k 기본값 = 60 (2009 Cormack 논문, 20년 가까이 유지). 튜닝이 거의 필요 없고 무관한 신호도 잘 융합한다. [HIGH]
  • Qdrant(v1.10+), Elasticsearch(rrf retriever), Weaviate, OpenSearch, Azure AI Search 가 RRF 를 내장한다. [MED]
  • 리랭킹: 초기 검색은 recall 최적화, 리랭커는 precision 최적화. 컨텍스트 한계로 top-5 만 넣어야 할 때 cross-encoder(Cohere rerank, bge-reranker)가 품질을 크게 올린다. top-20 을 리랭크 없이 그냥 넣는 건 낭비다. [MED]

청킹 전략

방식 특징
고정 크기(예 512토큰 + 50 overlap) 간단하지만 문장·문단 경계를 잘라 임베딩 품질 저하 [MED]
의미 기반(semantic) 문단·섹션·문장 자연 경계로 분할 [MED]
계층(hierarchical) 부모(섹션) + 자식(문장) 청크를 동시에 유지 [MED]

토큰 예산은 tokens-and-context-windows 로 계산하고, 무엇을 넣을지의 전략은 context-engineering 을 참고.

언제 벡터 검색이 필요 없나

벡터 검색을 반사적으로 붙이지 마라. 다음이면 건너뛴다.

  • 경계가 있는 1회성 분석: 계약서 한 건 검토, 정형 리포트 분석처럼 전체 자료를 컨텍스트에 넣는 비용이 감당되고 쿼리 패턴이 고정이면 롱컨텍스트가 더 단순하다. [MED]
  • 에이전틱 검색으로 충분할 때: 에이전트가 grep·파일 읽기·툴 호출로 필요한 조각을 직접 찾아오면 별도 벡터 인덱스가 불필요하다 (재확인 필요).
  • 10만 벡터 미만: 인덱스 없이 brute-force 로 충분하다. [MED]

단, 롱컨텍스트가 RAG 를 대체하는 건 아니다. 크거나 자주 변하는 컬렉션은 RAG 가 노이즈·토큰·지연·비용을 줄인다. attention 은 quadratic scaling 이라 컨텍스트를 키울수록 추론 비용이 급증하고 needle-in-haystack 실패 확률도 오른다. 롱컨텍스트와 RAG 는 서로 다른 제약에 맞는 도구다. [MED]

함정

  • DB 부터 바꾸는 실수: 검색이 나쁘면 임베딩·청킹·하이브리드를 먼저 의심하라. 벡터DB 교체는 대개 마지막 레버다.
  • 정규화 맹신: magnitude 에 의미가 있는 데이터를 정규화하면 신호를 지운다. 모델 학습 지표에 맞춰라.
  • BM25 생략: 식별자·코드·정확 인용이 중요한 도메인에서 순수 벡터만 쓰면 조용히 놓친다.
  • 리랭크 없이 top-20 투척: 컨텍스트 낭비 + 노이즈 유입. 넣기 전에 잘라라.
  • 차원 과욕: 3072차원이 1024차원보다 항상 낫지 않다. 비용만 늘고 recall 은 별 차이 없을 수 있다.

참고

출처: 대부분 [MED] aggregator 요약, RRF 공식·정규화 규칙만 [HIGH]. 벤치마크 점수는 규격상 인용하지 않음. 원본 → 2026-07-25-concepts-retrieval-quality