1장이 폐허를 보여 주었다면, 2장은 그 폐허 밑의 지반을 파 보는 장이다. 임베딩이라는 말없는 부품 — 애초에 어느 문서가 검색 후보가 될지를 결정해 온 그 부품 — 을 열어 보지 않고서는 어떤 검색 실패도 진단할 수 없다. 유물의 가치는 아는 만큼 보이고, 임베딩 공간의 실패도 읽을 줄 아는 만큼 보인다.
한 퀀트 애널리스트가 사내 리서치 RAG 시스템에 묻는다. "아르헨티나 2030 국채에 대한 우리의 익스포저는 얼마인가." 시스템은 세 개 펀드에 걸친 포지션을 인용하며 명목가치 약 4,700만 달러라는 자신만만한 요약을 돌려준다. 애널리스트는 그 수치를 리스크 메모에 적어 그날 아침 포트폴리오 매니저들에게 배포하고 다음 일로 넘어갔다.
그 수치는 네 배 가까이 어긋나 있었다. 실제 익스포저는 1억 8,200만 달러 — 채권의 ISIN 코드를 트레이딩 북과 대조해야만 확인되는 숫자였다. 시스템은 흔히 회자되는 "아르헨티나 2030"을 논한 문서들을 찾아 소액 보유 세 개 펀드의 포지션을 합산했을 뿐, 네 번째 펀드에 앉아 있던 훨씬 큰 포지션 — 내부 문서에서 통칭 대신 ISIN 코드로 기재된 — 은 별개의 결과로 검색해 아예 다른 채권으로 보고했다. 임베딩 모델에게 "Argentina 2030 sovereign bond"와 "ARARGE5202E6"은 의미적으로 유사하지 않았다. 가깝지도 않았다.
오류는 자기 기록과의 불일치를 알아챈 한 포트폴리오 매니저가 긴급 대조를 강행하면서 잡혔고, 피해는 봉쇄되었다. 그러나 사후 분석이 드러낸 문제는 청커나 리랭커나 프롬프트보다 깊은 곳에 있었다. 임베딩 모델 자체 — 애초에 어느 문서가 검색 후보가 될지를 결정해 온 말없는 부품 — 에게 채권의 이름과 ISIN의 등가성이라는 개념이 없었던 것이다. 시스템의 "유사성" 정의 전체가 이 도메인에는 틀린 정의였다.
이것은 고칠 수 있는 버그가 아니라, 임베딩 모델이 표상하는 의미와 회사가 실제로 쓰는 의미 사이의 건축적 불일치였다. 진지한 프로덕션 RAG를 출시해 본 팀이라면 누구나 언젠가 같은 벽에 부딪힌다. 임베딩 모델은 관련성에 관한 결정을 내리고 있는데, 시스템을 지은 엔지니어들은 그 결정을 검사한 적도, 검증한 적도, 흔히는 이해한 적도 없다는 벽 말이다. 이 장은 그 결정들을 이해하는 장이다. 대부분의 RAG 튜토리얼이 건너뛰는 장 — "문서를 임베딩하라"에서 "상위 k개를 검색하라"로 곧장 건너뛰며, 임베딩이 실제로 무엇을 하는지, 같은 뜻의 두 어구가 왜 멀리 떨어져 임베딩될 수 있는지는 살피지 않는 — 이기도 하다. 이 제1원리 없이는 2부와 3부의 기법들이 주문(呪文)에 지나지 않는다. 이것을 갖추면 모든 검색 실패가 진단 가능해지고, 모든 아키텍처 결정이 기본값이 아니라 의도된 트레이드오프가 된다.
임베딩은 텍스트 한 조각을 표상하는 고정 길이의 실수 벡터다. 이것이 기술적 정의이고, 이것만으로는 아무 쓸모가 없다. 임베딩이 왜 작동하는지 — 그리고 어디서 실패하는지 — 를 이해하려면 그 숫자들이 무엇을 뜻하는지, 어디서 왔는지, 의미 자체에 대해 어떤 가정을 품고 있는지를 알아야 한다.
기하학에서 시작하자. 언어 모델이 문장 하나를 이를테면 1,536차원으로 임베딩할 때, 모델은 그 문장을 1,536차원 공간의 한 점에 놓는 것이다. 모델이 지금껏 임베딩한 모든 문장과 앞으로 임베딩할 모든 문장이 바로 이 하나의 공간 어딘가에 산다. 임베딩 모델의 근본 주장은 이렇다. 이 공간에서 두 점 사이의 거리가 두 문장의 관계에 대해 유용한 것을 말해 준다. 가까운 문장은 더 관련되어 있고, 먼 문장은 덜 관련되어 있다는 것이다.
이 주장이 모든 벡터 검색 시스템의 주춧돌이다. 그리고 모델의 "관련됨"이 당신의 "관련됨"과 어긋날 때 모든 실패의 근원이 된다. 모델은 자신의 관련성 개념을 훈련 말뭉치 — 대개 웹, 책, 공개 자료에서 긁어모은 방대한 텍스트 — 에서 배웠다. "관련됨"이란 그 말뭉치에서 관찰된 공기(共起)와 문맥적 용법의 패턴, 딱 그만큼이다. 두 어구가 훈련 데이터에서 자주 함께 나타났으면 가깝게 임베딩되고, 그렇지 않았으면 도메인 전문가가 아무리 등가로 여기든 멀리 임베딩된다.
헤지펀드의 시스템이 "Argentina 2030 sovereign bond"와 "ARARGE5202E6"을 잇지 못한 까닭이 여기 있다. 두 어구가 모델의 훈련 말뭉치에 함께 등장했을 가능성은 거의 없다. 거래 시스템과 규제 서류에 쓰이는 구조화 식별자인 ISIN은 공개 임베딩 모델이 학습하는 일반 영어 텍스트에서 희귀하다. 채권의 통칭은 흔하다. 모델에게 하나는 거의 무의미한 코드이고 다른 하나는 익숙한 금융 용어다. 등가성을 세워 주는 훈련 데이터가 주어지지 않는 한, 둘이 같은 상품을 가리킨다는 것을 모델이 배울 방도는 없다.
애초에 이 벡터는 어떻게 만들어지는가. 현대의 임베딩 모델은 트랜스포머다 — 그것이 곁들여 쓰이는 대형 언어 모델과 같은 건축 계열이다. 트랜스포머는 토큰열을 읽고 여러 층의 어텐션과 순전파 연산으로 정보를 흘려 보내 모든 층의 모든 토큰에 대한 표상을 만든다. 이를 시퀀스 전체에 대한 하나의 고정 길이 임베딩으로 바꾸기 위해 풀링 연산 — 대개 마지막 층 토큰 표상의 평균, 또는 시퀀스를 요약하는 전용 분류 토큰 — 을 쓴다. 결과는 일반적으로 384에서 3,072차원 사이의 단일 벡터, 모델이 입력의 의미를 요약한다고 주장하는 그 벡터다.
이 과정에는 깊은 한계가 묻혀 있다. 모델은 임의 길이의 텍스트를 고정 길이 벡터로 압축하고 있다. 세 단어짜리 문장도, 삼백 단어짜리 문서도 같은 차원 수로 환원된다. 정보는 사라진다. 무엇을 남기고 무엇을 버릴지는 — 훈련 방식에 의해 암묵적으로 — 모델이 정한다. 대부분의 범용 질의에서 모델은 상위 주제를 남기고 세부를 버린다. "아르헨티나 국가부채에 대해 알려 달라"는 질의라면 괜찮다. "ISIN ARARGE5202E6에 대한 우리의 익스포저는 얼마인가"라는 질의라면 파국적이다. 세부가 관건인데, 임베딩은 그것을 이미 내다 버렸기 때문이다.
이 압축을 이해하는 것이 임베딩이 통할 때와 통하지 않을 때를 가르는 열쇠다. 임베딩은 의미적 주제, 넓은 화제, 흔한 생각의 환언, 훈련 데이터에 있던 개념적 관계를 잡아내는 데 탁월하다. 정밀한 식별자, 희귀 용어, 수치 관계, 부정문, 훈련 데이터에 없던 도메인 특유의 등가성을 잡아내는 데는 미덥지 못하다. 프로덕션급 RAG 시스템은 바로 이 구별 위에 지어진다 — 임베딩이 잘하는 일에는 임베딩을 쓰고, 그 밖의 모든 것에는 다른 기제(키워드 검색, 구조화 조회, 지식 그래프)를 쓴다.
임베딩은 텍스트 한 조각을 기하 공간의 한 점에 놓는 고정 길이 벡터 — 통상 384~3,072차원 — 다. 두 점 사이의 거리는 두 텍스트가 얼마나 관련되어 있는지에 대한 모델의 추정치다.
임베딩은 어떤 절대적 의미에서의 의미 표상이 아니다. 그것은 모델의 훈련 말뭉치에 나타난 공기와 문맥적 용법의 패턴을 반영하는 학습된 압축이다. 당신의 말뭉치가 지닌 관련성 개념이 훈련 말뭉치의 그것과 다를 때, 임베딩은 순수 벡터 검색으로는 탐지할 수 없는 방식으로 실패한다.
의미적 간극은 프로덕션 검색 실패의 단일 최대 원인이다. 사람이라면 뜻이 같다고 여길 두 어구가, 벡터 검색이 무관하다고 취급하는 임베딩을 낳을 수 있다. 그 이유를 — 그리고 대책을 — 아는 것이 데모에서 도는 시스템과 프로덕션에서 버티는 시스템의 갈림길이다.
헤지펀드 사례는 간극의 가장 극단적인 형태 — 한쪽은 구조화 식별자, 다른 쪽은 통칭 — 를 보여 주었다. 그러나 간극은 훨씬 일상적인 모습으로도 나타난다. "구독을 어떻게 해지하나"와 "계정 해지 절차"는 표면 어휘를 하나도 공유하지 않는다. "경증 간기능 장애"와 "Child-Pugh Class A"는 임상적 동의어지만 전혀 다른 용어를 쓴다. "3분기 매출이 전망을 상회했다"와 "매출이 3분기 시장 기대치를 웃돌았다"는 단어를 거의 공유하지 않는 환언이다. 모든 경우에 사용자의 어휘와 말뭉치의 어휘가 같은 개념을 다르게 표현한다. 임베딩 모델은 그 간극을 이어 주기로 되어 있고 — 이을 때도 있고, 잇지 못할 때도 있다.
모델이 간극을 잇느냐는 두 표현의 등가성이 훈련 데이터에 나타났느냐에 달렸다. "car"와 "automobile", "physician"과 "doctor"처럼 그 텍스트에 자주 나오는 등가성은 잘 학습된다. 도메인 전문 용어, 사내 용어, 구조화 식별자, 갓 만들어진 용어처럼 나오지 않는 것들은 학습되지 않는다. 그 경계는 흐릿하고, 문서화되어 있지 않으며, 임베딩 모델마다 사실상 예측 불가능하게 다르다. 여기서 대부분의 팀이 부딪히기 전에는 실감하지 못하는 실무적 함의가 나온다. 임베딩 모델은 블로그 글이나 벤치마크로 고를 수 없다. 벤치마크는 당신의 도메인을 반영하지 않았을 것이고, 블로그 글의 필자는 당신의 말뭉치를 가져 본 적이 없다. 믿을 만한 유일한 방법은 실제 말뭉치 위에서 대표 질의로 시험하고 고정된 k에서 검색 재현율을 재는 것이다. 원칙은 이렇다 — 모든 프로덕션 RAG 시스템은 대표 질의 집합에 대해 k=10과 k=50에서의 재현율을 알아야 하고, 임베딩 모델이나 말뭉치가 바뀔 때마다 다시 재야 한다.
의미적 간극에는 세 개의 수원(水源)이 있고, 따로 다루는 편이 더 나은 공학적 결정으로 이끈다. 첫째는 어휘 — 같은 개념, 다른 낱말. 임베딩 모델이 잇도록 설계된 종류이고, 흔한 용어라면 자주 잇는다. 둘째는 구조 — 같은 개념, 다른 표상 형식(이름 대 코드, 질문 대 진술, 환언 대 인용). 임베딩 모델이 미덥지 못한 종류다. 셋째는 입도(粒度) — 같은 개념, 다른 추상 수준. 임베딩이 눈에 띄지 않게 실패하는 곳으로, 임베딩끼리 그럴듯하게 닮아서 검색이 그럴싸한 결과를 돌려주지만 실제 의미 대응은 엉뚱한 척도에서 일어난다.
부정의 경우는 특별히 눈여겨보아야 한다. 대조 학습으로 훈련된 임베딩 모델 — 요즘 모델 대부분이 그렇다 — 은 "이 약에는 알려진 부작용이 있다"와 "이 약에는 알려진 부작용이 없다"를 매우 가까운 위치에 임베딩하는 경향이 있다. 모델은 두 문장이 모두 부작용에 관한 것임을 배웠고, 진술의 극성(極性)은 압축 속에서 유실된다. 극성이 관건인 프로덕션 시스템 — 의약 금기, 법적 배제 조항, 금융 제한 — 에서 순수 벡터 검색은 정확히 반대의 문서를 높은 확신으로 돌려줄 수 있다. 이것이 5장에서 전개할 하이브리드 검색을 지지하는 가장 강력한 논거의 하나다.
그렇다면 의미적 간극은 실제로 어떻게 우회하는가. 비용과 효과가 커지는 순서로 다섯 가지다. 첫째, 질의 재작성 — 사용자의 질문을 말뭉치 어휘에 닿기 쉬운 하나 이상의 재구성으로 변환한다. 둘째, 질의 확장 — 동의어, 관련어, 도메인 별칭을 질의에 보탠다. 셋째, 하이브리드 검색 — 임베딩이 실패할 때 정확 일치가 놓치지 않도록 벡터 유사도에 키워드 검색을 결합한다. 넷째, 도메인 적응 임베딩 — 범용 모델의 도메인 특화판 또는 미세조정판을 쓴다. 다섯째, 수집 시점의 구조화 등가성 구축 — 식별자를 이름에, 코드를 설명에 잇는 조회 테이블을 만들어 검색이 알아야 할 도메인 등가성을 명시한다. 대부분의 프로덕션 시스템은 이 중 서너 개를 결합해 쓴다. 하이브리드 검색은 진지한 배포라면 협상의 여지가 없고, 도메인 적응은 말뭉치가 전문 분야일 때마다 필수이며, 구조화 등가성은 식별자·코드·희귀 고유명사가 중요할 때마다 필수다. 질의 재작성과 확장은 가장자리를 다듬는 유용한 보탬이다.
프로덕션에서 가장 흔한 임베딩 실수는 전문 도메인에 범용 임베딩 모델(text-embedding-3-small, all-MiniLM-L6-v2 등)을 쓰고 잘되기를 바라는 것이다. 의료·법률·금융·공학 말뭉치에서 범용 임베딩의 검색 재현율은 도메인 적응 대안보다 통상 15~30% 낮다. 서너 개 모델을 대표 질의로 평가하는 비용은 며칠이고, 잘못된 모델로 출시하고 나중에 발견하는 비용은 몇 달의 수습이다. 확정 전에 반드시 평가하라.
프로덕션 검색 공학은 "유사도"가 하나가 아님을 아는 데서 출발한다. 유사도에는 적어도 세 갈래의 뚜렷한 가계(家系)가 있고, 각각 쓰일 자리가 다르며, 각각 제 나름의 강점과 실패 양식을 지닌다. 한 갈래만 쓰는 시스템은 나머지 두 갈래가 감당하도록 설계된 상황에서 반드시 실패한다. 건축가의 안목이란 자기 응용이 실제로 어느 갈래를 — 혹은 어떤 조합을 — 필요로 하는지 알아보는 눈이다. 절집의 아름다움이 기둥 하나에 있지 않고 배흘림과 공포와 지붕 물매의 어울림에 있듯, 검색의 힘도 세 갈래의 어울림에서 나온다.
같은 낱말을 공유하면 유사하다. 어간 추출과 활용을 어느 정도 허용하되, 기준은 표면 어휘다. 반세기 동안 다듬어진 BM25 — 항 빈도, 역문서 빈도, 문서 길이 정규화의 가중 결합 — 가 2026년에도 지배적 알고리즘이며, 모든 검색 시스템이 견주어야 할 기준선으로 남아 있다.
강점 — 정확하고, 해석 가능하고, 예측 가능하다. "acetaminophen"을 물으면 그 낱말을 담은 문서를 찾는다. 끝. 질의와 결과 사이에 보이지 않게 실패할 압축층이 없다.
약점 — 동의어, 환언, 의미 관계를 전적으로 놓친다. "구독 해지"로는 "계정 해지"만 쓰는 말뭉치에서 아무것도 찾지 못하며, 어휘 패러다임 안에서는 고칠 길이 없다.
표면 어휘와 무관하게 관련 개념을 표현하면 유사하다. 표준 척도는 코사인 유사도 — 두 벡터 사이 각의 코사인, −1(반대)에서 1(같은 방향) 사이의 값 — 로, 크기가 아니라 방향이 관건이라는 기하학적 직관이다. 코사인 기반 대조 손실로 훈련된 현대 모델 대부분에 맞는 선택이다.
강점 — 어휘가 실패하는 바로 그곳에서 빛난다. 환언, 동의어, 개념 관계, 언어 간 대응. "구독을 어떻게 해지하나"가 "계정 해지 정책"과 만나는 것은 두 어구가 임베딩 공간의 이웃 동네에 살기 때문이다.
약점 — 어휘가 성공하는 곳에서 실패한다. 정확한 식별자 대응, 희귀 용어, 극성 민감 질의, 일반 화제보다 특정 낱말이 중한 모든 경우.
표면 텍스트나 개별 구절의 의미와 무관하게, 서술하는 엔티티·관계·역할이 겹치면 유사하다. 지식 그래프가 포착하는 가계이고, GraphRAG가 그 위에 서 있다.
강점 — "우리 공급업체 중 최근 제재받은 경쟁사와 이사를 공유하는 곳은?" 어휘도 의미도 이 질문에 답하지 못한다. 답은 어느 구절에도 없고 공급업체 명부, 이사회 명단, 규제 조치 공고 사이의 관계에만 있다. 수사형 질의, 컴플라이언스 질의, 공급망 질의, 대부분의 멀티홉 질문이 이 가계의 영토다.
약점 — 그래프를 지어야 쓸 수 있다. 6장이 구현 깊이로 전개한다.
세 가계를 나란히 세워 보는 짧은 실험 하나가 원서에 실려 있다. MedCentral을 닮은 세 문장의 말뭉치에 "Child-Pugh Class A 환자의 안전 용량은?"을 묻는 것이다.
# 세 갈래 유사도 가계의 간단한 시연 from rank_bm25 import BM25Okapi from sentence_transformers import SentenceTransformer import numpy as np corpus = [ "The patient was prescribed acetaminophen 4000 mg daily.", "For mild hepatic impairment, maximum daily dose is 2000 mg.", "The drug is contraindicated in liver disease.", ] query = "What is the safe dose for Child-Pugh Class A patients?" # 어휘적: 표면 어휘가 겹치지 않아 BM25는 아무것도 찾지 못한다 tokenized = [doc.lower().split() for doc in corpus] bm25 = BM25Okapi(tokenized) lexical_scores = bm25.get_scores(query.lower().split()) print(f"Lexical: {lexical_scores}") # 모두 0에 가깝다 # 의미적: 임베딩이 '경증 간기능 장애'와 'Child-Pugh A'를 잇는다 model = SentenceTransformer('all-MiniLM-L6-v2') doc_embs = model.encode(corpus) query_emb = model.encode([query])[0] semantic_scores = np.dot(doc_embs, query_emb) / ( np.linalg.norm(doc_embs, axis=1) * np.linalg.norm(query_emb)) print(f"Semantic: {semantic_scores}") # 대개 두 번째 문서가 최고점 — 옳게 # 구조적 유사도라면 'Child-Pugh A'와 '경증 간기능 장애'를 임상 동의어로 # 잇는 지식 그래프가 필요하다 — 6장에서 다룬다.
이 코드의 교훈은 어느 가계가 이긴다는 것이 아니다. 각 가계가 말뭉치의 서로 다른 면을 비춘다는 것이다. 어휘 검색은 사용자가 정확한 용어를 알 때, 의미 검색은 일상어로 전문 내용을 물을 때, 구조 검색은 멀티홉과 수사형 질의에서 제 몫을 한다. 세 갈래를 하나의 파이프라인 — 그래프 탐색으로 확장된 하이브리드 검색 — 에 결합한 프로덕션 시스템, 그것이 이 책의 나머지가 지어 나가는 목적지다.
임베딩 모델 선택은 어느 프로덕션 RAG 시스템에서든 가장 지렛대가 큰 결정에 속한다. 잘못 고르면 하류 전체가 그 한계에 갇히고, 잘 고르면 파이프라인의 다른 어떤 것도 바꾸지 않고 검색 재현율을 15~30% 끌어올릴 수 있다. 그런데도 대부분의 팀은 이 결정을 대수롭지 않게 내린다 — 인기 튜토리얼이 쓰던 것, 이미 계정이 있는 제공자의 것으로 기본값을 삼는 식이다. 2026년에 고려할 만한 계급은 셋이고, 제대로 들여다보면 선택이 아슬아슬한 경우는 드물다.
모델 계급 너머로 구현 결정이 둘 남는다. 첫째는 차원 수다. 임베딩 모델은 384차원(작고 빠르고 품질 낮음)에서 3,072차원(크고 느리고 품질 최고)에 걸친다. 차원이 높을수록 뉘앙스를 더 담지만 저장과 검색 비용이 커진다. 문서 백만 건 이하의 말뭉치라면 768~1,536차원이 최적 지대이고, 그보다 크면 고차원 벡터의 저장·검색 비용이 지배하기 시작해 차원 축소 기법(Matryoshka 표상, PCA, 학습된 투영층)을 저울질할 가치가 생긴다.
둘째는 문서당 단일 벡터냐 다중 벡터냐다. ColBERT, DRAGON 등 후기 상호작용(late-interaction) 계열의 다중 벡터 접근은 토큰이나 청크를 따로 임베딩하고 질의 시점에 더 정교한 매칭을 수행해, 검색 벤치마크에서 단일 벡터를 흔히 10~15% 앞선다. 대가는 전용 인프라(대부분의 벡터 데이터베이스는 단일 벡터용으로 설계되었다)와 더 느리고 비싼 서빙이다. 검색이 병목인 고위험 시스템에서는 다중 벡터가 점점 정답이 되어 가고, 대부분의 시스템에서는 단일 벡터에 재순위화(5장)를 얹는 편이 그 이득의 대부분을 훨씬 싼값에 얻는다.
임베딩 모델을 고르는 옳은 방법은 대표 질의 오십 개로 서너 후보를 말뭉치의 대표 단면 위에서 평가하는 것이다. 미세조정도, 인프라 변경도, 질의 집합 이상의 학습 데이터도 필요 없다. 이 평가를 건너뛴 팀은 프로젝트 수개월 차에, 자기들이 고칠 수 있는 무엇도 아닌 임베딩 모델이 검색의 상한이었음을 발견하곤 한다. 시작의 이틀이 중반의 두 달을 아낀다. 반드시 평가하라.
이 장의 마지막 규율은 진단이다. 프로덕션에서 검색이 실패할 때, 실패는 임베딩 공간에서 일어난다 — 그리고 그것을 이해하는 유일한 길은 임베딩 자체를 들여다보는 것이다. 대부분의 팀이 끝내 기르지 못하는 안목인데, 임베딩이 블랙박스처럼 느껴지기 때문이다. 그러나 그것은 블랙박스가 아니다. 벡터다. 검사할 수 있고, 시각화할 수 있고, 추론할 수 있다. 이 안목을 기른 팀은 검색 실패를 몇 시간 만에 진단하고, 기르지 못한 팀은 몇 주씩 증상만 뒤쫓는다. 개발할 가치가 있는 진단 기법은 다섯이며, 어느 것도 고급 전문성을 요구하지 않는다.
어느 질의든, 질의와 말뭉치 사이 코사인 유사도의 분포가 말해 주는 것이 있다. 건강한 시스템의 분포는 이봉이다 — 높은 유사도(통상 0.7 이상)의 고관련 문서 소수, 낮은 유사도(통상 0.3 이하)의 무관 문서의 긴 꼬리, 그리고 둘 사이의 골. 분포가 단봉 — 모든 문서가 비슷한 중간 점수 — 이면 임베딩 모델이 판별에 실패하고 있는 것이고, 검색은 사실상 무작위다. 대표 질의 열~스무 개의 분포를 그려 보는 것이 검색 디버깅에서 가장 많은 정보를 주는 단 하나의 행위다.
말뭉치에서 확실히 좋은 답 문서 하나를 골라 임베딩하고 그 최근접 이웃들을 찾아본다. 도메인 전문가인 당신이 관련 있다고 여길 문서들이어야 한다. 그렇지 않다면 — 임상 가이드라인의 이웃이 임상 세부라곤 없는 환자 교육 자료뿐이라면 — 임베딩 모델이 당신의 도메인에서 실패하고 있다는 직접 증거다. 몇 분이면 되고, 즉시 행동으로 옮길 통찰을 준다.
대표 질의 집합에 대해, 질의 임베딩과 정답을 담은 문서의 임베딩 사이 간격을 잰다. 간격이 크다면 — 정답 문서가 최근접 오십 안에도 없다면 — 어떤 재순위화도 구원하지 못한다. 재순위화가 시작되기도 전에 검색이 이미 실패한 것이다. 이 진단이 검색 실패와 순위 실패를 가르며, 둘의 처방은 다르다.
말뭉치 임베딩 전체에 걸쳐 각 차원의 분산을 계산한다. 분산이 극히 낮은 차원은 이 말뭉치에 대해 정보를 나르지 않으며 때로 버릴 수 있다. 분산이 매우 높은 차원이 판별 작업의 대부분을 한다. 소수의 차원만이 분산의 대부분을 진다면 임베딩이 제 능력을 놀리고 있는 것 — 대개 모델이 도메인에 비해 너무 범용이라는 신호다.
UMAP이나 t-SNE로 말뭉치 임베딩을 2~3차원에 투영해 그려 본다. 관련 문서의 군집, 잘못 분류되었을 수 있는 고립 문서, 화제 영역 간의 기하학적 관계 — 말뭉치의 거시 구조가 드러난다. 시각화가 정량 분석을 대신하지는 못하지만, 정량 분석만으로는 놓칠 구조적 패턴을 어김없이 드러낸다.
# 진단 레시피 — 검색이 이상하다 싶을 때마다 돌린다 import numpy as np import matplotlib.pyplot as plt from sentence_transformers import SentenceTransformer import umap model = SentenceTransformer('all-MiniLM-L6-v2') doc_embs = model.encode(corpus) # corpus: 청크 목록 query_embs = model.encode(queries) # queries: 테스트 질의 집합 # 1. 거리 분포 — 기대하는 이봉 패턴이 보이는가? for q_emb in query_embs: sims = doc_embs @ q_emb / (np.linalg.norm(doc_embs, axis=1) * np.linalg.norm(q_emb)) plt.hist(sims, bins=40) plt.title('Similarity distribution — expect bimodal') plt.show() # 2. 차원 분산 — 몇 차원이 실제로 정보를 나르는가? variances = np.var(doc_embs, axis=0) print(f'Effective dimensions (variance > 0.001): ' f'{(variances > 0.001).sum()} / {len(variances)}') # 3. 말뭉치 시각화 — 거시 구조는 어떤 모양인가? reducer = umap.UMAP(n_components=2, random_state=42) coords = reducer.fit_transform(doc_embs) plt.scatter(coords[:, 0], coords[:, 1], alpha=0.3) plt.title('Corpus structure — look for clean clusters or noise') plt.show()
이 다섯 진단을 함께 돌리면, 검색 시스템이 구조적으로 건전한지 임베딩이 발목을 잡고 있는지가 오후 한나절 안에 드러난다. 이것이 진단의 전부는 아니다 — 10장이 더 완전한 관측 가능성 프레임워크를 세운다 — 그러나 모든 RAG 엔지니어가 언제든 돌릴 수 있어야 할 것들이다. 돌리는 비용은 몇 시간이고, 돌리지 않는 비용은 프로젝트 일정을 무너뜨리는 석 달짜리 디버깅의 수렁이다.
가장 흔한 임베딩 관련 실수는 처음 잡은 프레임워크의 기본 모델을 말뭉치에 대한 시험 한 번 없이 쓰는 것이다. LangChain의 기본값은 OpenAI text-embedding-3-small이고 LlamaIndex도 비슷하다. 일반 영어 콘텐츠에는 합리적인 기본값이지만, 의료·법률·금융·과학, 그리고 대부분의 기업 말뭉치에는 틀린 기본값이다.
처방 — 확정 전에 시험하라. 비용은 이틀이다.
두 문서의 코사인 유사도가 0.92라면 매우 관련되어 있다고 여기는 것이 자연스러운 반사다. 아닐 수 있다. 코사인 유사도는 관련성에 대한 임베딩 모델의 믿음을 반영할 뿐, 실제로 참인 것을 반영하지 않는다.
처방 — 고위험 도메인에서는 어떤 결정이 걸리기 전에 모든 검색 결과를 실제 문서 내용에 대조해 검증하라. 유사도 점수는 결론이 아니라 가설이다.
임베딩 모델은 의미가 정반대인 진술을 예사로 가깝게 임베딩한다. "이 약에는 알려진 부작용이 있다"와 "없다"는 통상 코사인 유사도 90%를 넘고, "환자는 페니실린에 알레르기가 있다"와 "없다"도 같은 병을 앓는다.
처방 — 극성·부정·수치 정확성이 관건인 시스템 — 의료, 법률, 금융, 안전 필수 공학 — 에서 순수 벡터 검색은 근본적으로 불충분하다. 하이브리드 검색과 구조화 검증은 협상의 여지가 없다.
임베딩은 텍스트를 기하 공간의 한 점에 놓는 고정 길이 벡터이며, 모델의 '관련됨'이란 훈련 데이터에서 관찰한 공기 패턴 그 자체다. 그 개념이 당신의 것과 다를 때, 검색은 순수 벡터 유사도로는 탐지할 수 없는 방식으로 실패한다.
의미적 간극 — 사용자 어휘와 말뭉치 어휘의 단절 — 이 검색 실패의 최다 원인이다. 어휘·구조·입도의 세 형태가 있고, 각각 다른 공학적 응답을 요구하며, 대부분의 프로덕션 시스템은 하이브리드 검색·도메인 적응·구조화 등가성의 조합을 필요로 한다.
유사도는 하나가 아니다. 어휘적·의미적·구조적의 세 가계가 있고 각각 쓰일 자리가 다르다. 프로덕션급 검색 시스템은 어느 하나에 기대지 않고 셋을 결합한다.
임베딩 모델 선택은 RAG 시스템에서 가장 지렛대가 크면서 가장 저평가된 결정이다. 범용 임베딩은 전문 말뭉치에서 도메인 적응 대안에 15~30% 뒤진다. 그 차이를 드러내는 평가의 비용은 이틀이다. 확정 전에 반드시 평가하라.
검색 진단은 블랙박스가 아니라 기술이다. 거리 분포 분석, 최근접 이웃 검사, 질의–문서 정렬, 차원 분산, 임베딩 공간 시각화 — 모든 RAG 엔지니어가 언제든 돌릴 수 있어야 할 다섯 도구가 몇 주짜리 디버깅의 수렁을 오후 한나절의 조사로 바꾼다.
위 문헌 목록은 원서 2장의 Further Reading을 그대로 옮긴 것이다. 서지 사항의 최종 확인은 원 출처를 통해 하는 것이 옳다.
3장은 임베딩의 이론에서 임베딩의 공학으로 건너간다. 말뭉치를 규모 있게 임베딩하는 실무적 결정들 — 벡터 데이터베이스의 선택, 호스팅과 자체 운영 사이의 트레이드오프, 임베딩 생성과 저장의 운영 관심사, 문서가 변할 때 임베딩을 최신으로 유지하는 패턴 — 을 다룬다. 이 장의 개념적 기초가 있으면 그 공학적 결정들이 손에 잡히고, 없으면 어림짐작이 된다. 주춧돌을 보았으니 이제 기둥을 세울 차례다.