Skip to main content
임베딩은 RAG의 기초 중의 기초입니다. 임베딩 품질이 RAG 전체 품질의 70%를 좌우한다고 해도 과언이 아닙니다. 이 페이지에서는 임베딩이 왜 필요한지, 어떻게 동작하는지, 그리고 실무에서 어떻게 활용하는지를 깊이 있게 다룹니다.

왜 필요한가: 컴퓨터의 텍스트 이해 한계

컴퓨터에게 텍스트는 본질적으로 문자 코드의 나열 입니다. “오늘 날씨가 좋다”는 [50724, 45765, 32...] 같은 유니코드 숫자일 뿐입니다. 문자열 비교 로는 의미를 알 수 없습니다:
"자동차 보험 가입 방법" vs "차량 보험 신청 절차"
→ 문자열 비교: 완전히 다른 텍스트 (일치율 낮음)
→ 의미 비교: 거의 동일한 의미 (유사도 0.95)
반대로, 문자열이 비슷해도 의미가 다를 수 있습니다:
"이 영화 정말 못 봐주겠다" vs "이 영화 정말 못 보겠다 (시간이 없어서)"
→ 문자열 비교: 매우 유사
→ 의미 비교: 전혀 다른 의도 (부정적 평가 vs 시간 부족)
임베딩은 이 문제를 해결합니다. 텍스트를 의미를 반영한 숫자 벡터 로 변환하여, 컴퓨터가 의미 수준에서 텍스트를 비교할 수 있게 합니다.

역사: 단어에서 문장으로, 문장에서 다국어로

연도모델혁신
2013Word2Vec단어를 벡터로 변환. “왕 - 남자 + 여자 = 여왕” 같은 벡터 연산 가능
2014GloVe전체 코퍼스의 동시 출현 통계를 활용하여 더 안정적인 벡터 생성
2018BERTTransformer 아키텍처 도입. 문맥에 따라 같은 단어도 다른 벡터 생성
2019Sentence-BERTBERT를 문장 단위 유사도 비교에 최적화. 실용적 임베딩의 시작
2023~E5 / BGE / GTE대규모 학습, 다국어 지원, 높은 차원의 의미 포착. 현재 SOTA
이 흐름의 핵심은 “단어 → 문맥 → 문장” 으로 임베딩 단위가 확장된 것입니다. Word2Vec 은 주변 단어 예측(Skip-gram) 또는 주변 단어로 중심 단어 예측(CBOW)이라는 단순한 신경망 학습을 통해, 비슷한 문맥에 등장하는 단어는 비슷한 벡터를 갖도록 학습합니다. 하지만 한 단어에 하나의 고정 벡터만 부여하므로 다의어(예: “은행”)를 구분할 수 없었습니다. GloVe 는 Word2Vec과 달리 전체 코퍼스에서 단어 쌍의 동시 출현 빈도를 행렬로 만들고, 이 행렬을 분해(factorization)하여 벡터를 생성합니다. 전역 통계를 활용하므로 Word2Vec보다 안정적이지만, 여전히 단어당 하나의 고정 벡터라는 한계는 동일합니다. BERT 가 게임 체인저가 된 이유는 Transformer의 Self-Attention(입력의 모든 토큰이 서로의 관련성을 계산하는 메커니즘)을 통해, 같은 단어라도 주변 문맥에 따라 매번 다른 벡터 를 동적으로 생성하기 때문입니다. 하지만 BERT로 두 문장의 유사도를 구하려면 두 문장을 하나로 연결하여 모델에 넣어야 해서, N개 문서 비교 시 N번의 추론이 필요하다는 효율 문제가 있었습니다. Sentence-BERT(SBERT) 는 Siamese Network(샴 네트워크, 두 입력을 동일 구조의 네트워크에 각각 통과시켜 비교하는 아키텍처) 구조를 도입하여, 각 문장을 독립적으로 한 번만 인코딩 해서 고정 크기 벡터를 얻을 수 있게 했습니다. 이 덕분에 사전에 모든 문서를 벡터로 변환해 저장한 뒤, 쿼리 벡터와 빠르게 비교하는 현대적 벡터 검색이 가능해졌습니다.
참고 핵심 전환점: Word2Vec은 “은행(금융)“과 “은행(강가)“을 구분하지 못했습니다. BERT 이후부터는 주변 문맥을 고려하여 같은 단어도 다른 벡터를 생성합니다. 이를 contextualized embedding 이라 합니다.

동작 원리: Transformer Encoder의 내부

현대 임베딩 모델은 Transformer의 Encoder 부분을 사용합니다:
  1. 토큰화: 입력 텍스트를 토큰(subword, 단어보다 작은 단위로 분리한 조각)으로 분리합니다. 예를 들어 “데이터브릭스”는 “데이터”, “브”, “릭”, “스”처럼 분리될 수 있습니다. 이렇게 하는 이유는 모든 단어를 사전에 등록할 수 없으므로, subword 조합으로 미등록 단어도 표현하기 위해서입니다.
  2. Self-Attention: 각 토큰이 다른 모든 토큰과의 관계를 계산합니다. 구체적으로, 각 토큰은 자신을 Query(질문), Key(키), Value(값) 세 벡터로 변환합니다. Query와 Key의 내적으로 attention score(관련성 점수) 를 구한 뒤, 이 점수로 Value를 가중 합산하여 문맥이 반영된 새로운 벡터를 만듭니다. 예를 들어 “은행에서 대출을 받았다”에서 “은행”의 Query가 “대출”의 Key와 높은 점수를 받으면, “대출”의 의미 정보가 “은행” 벡터에 많이 반영되어 “금융 기관”으로 해석됩니다. 이 과정이 12~24개 레이어에 걸쳐 반복되면서 점점 더 풍부한 문맥 표현이 만들어집니다.
  3. 벡터 추출(Pooling): 모든 토큰의 벡터를 하나의 문장 벡터로 압축합니다. 두 가지 방법이 있습니다:
    • CLS 토큰: 문장 시작에 추가된 특수 토큰 [CLS]의 벡터를 전체 문장의 대표 벡터로 사용합니다. BERT의 사전 학습에서 [CLS]는 문장 전체의 의미를 집약하도록 훈련되었기 때문입니다. 하지만 실제로는 [CLS]가 문장 전체를 충분히 대표하지 못하는 경우가 있습니다.
    • Mean Pooling: 모든 토큰 벡터의 요소별 평균을 계산합니다. 모든 토큰의 정보가 골고루 반영되므로 최근 모델(E5, BGE 등)에서 더 선호됩니다. 연구 결과 Mean Pooling이 CLS 대비 대부분의 벤치마크에서 1-3% 더 높은 성능을 보입니다.
입력: "Databricks에서 벡터 검색을 설정합니다"

[CLS] Databricks 에서 벡터 검색 을 설정 합니다 [SEP]
  ↓      ↓       ↓    ↓    ↓   ↓   ↓    ↓     ↓
 v_cls  v_1     v_2   v_3  v_4 v_5 v_6  v_7   v_sep

→ CLS 방식: v_cls 를 문장 벡터로 사용
→ Mean Pooling: (v_1 + v_2 + ... + v_7) / 7 을 문장 벡터로 사용

차원의 의미: 추상적인 “의미 축”

임베딩 벡터의 각 차원은 사람이 직접 해석하기 어려운 추상적인 의미 축 을 나타냅니다. 하지만 직관적으로 이해하면:
  • 어떤 차원은 “긍정-부정” 축과 비슷할 수 있음
  • 어떤 차원은 “기술적-비기술적” 축과 비슷할 수 있음
  • 어떤 차원은 “과거-현재-미래” 시제 축과 비슷할 수 있음
768차원 벡터라면 768개의 이런 추상적 의미 축에서의 위치가 기록되는 것입니다. 차원이 높을수록 더 세밀한 의미 구분이 가능하지만, 계산 비용도 증가합니다.

실제 예시: 다국어 임베딩의 힘

다국어 임베딩 모델(BGE-M3, E5-multilingual 등)은 언어가 달라도 같은 의미면 가까운 벡터 를 생성합니다:
"데이터베이스 성능 최적화 방법"  →  [0.23, -0.41, 0.67, ...]
"How to optimize database performance" →  [0.22, -0.40, 0.68, ...]
→ 코사인 유사도: 0.96 (매우 유사!)

"오늘 점심 뭐 먹지"  →  [-0.15, 0.82, -0.33, ...]
"데이터베이스 성능 최적화 방법"  →  [0.23, -0.41, 0.67, ...]
→ 코사인 유사도: 0.08 (거의 무관)
이 덕분에 한국어로 질문해도 영어 문서를 검색할 수 있고, 그 반대도 가능합니다.

임베딩 품질의 중요성: “Garbage In, Garbage Out”

주의 RAG 품질의 70%는 임베딩 품질에 의존합니다. 아무리 정교한 Re-ranking, 하이브리드 검색, 프롬프트 엔지니어링을 적용해도, 임베딩 단계에서 의미를 제대로 포착하지 못하면 관련 문서가 검색 후보에 포함되지 않습니다. 후보에 없는 문서는 어떤 후처리로도 복구할 수 없습니다.
임베딩 품질을 좌우하는 요소:
  1. 모델 선택: 도메인에 맞는 모델 (의료, 법률, 기술 등). 일반 모델은 도메인 전문 용어의 의미를 정확히 포착하지 못할 수 있습니다. 예를 들어, 일반 모델에서 “판”은 법률 문서의 “판결”과 일상어 “판”을 구분하기 어렵습니다. MTEB(Massive Text Embedding Benchmark) 리더보드에서 대상 언어/도메인에 적합한 모델을 선택하는 것이 첫 단계입니다.
  2. 입력 품질: 청킹(chunking, 긴 문서를 의미 단위로 분할하는 작업)이 잘못되어 의미가 잘린 텍스트는 좋은 임베딩을 만들 수 없습니다. “결론적으로 이 방법은”이라는 문장이 앞 문맥 없이 청크의 시작이 되면, 임베딩 모델은 “이 방법”이 무엇인지 알 수 없어 무의미한 벡터를 생성합니다.
  3. 다국어 지원: 한국어가 포함된다면 다국어 모델 필수. 영어 전용 모델에 한국어를 넣으면, 토크나이저가 한국어를 개별 바이트로 분리하여 의미 포착이 크게 저하됩니다.
  4. Fine-tuning: 도메인 특화 데이터로 추가 학습하면 품질 향상. 구체적으로, (질문, 관련 문서) 쌍을 수백~수천 개 준비하여 contrastive learning(대조 학습, 유사 쌍은 가깝게/비유사 쌍은 멀게 학습) 으로 미세 조정합니다. 도메인 fine-tuning만으로 검색 정확도가 5-15% 향상되는 사례가 일반적입니다.

Databricks에서의 임베딩 활용

방법설명사용 시나리오
Foundation Model APIServing Endpoint로 임베딩 모델 호출Python/API에서 직접 임베딩 생성
ai_query()SQL 함수로 임베딩 생성SQL 파이프라인 내에서 임베딩
Vector Search 자동 임베딩Delta Sync Index 생성 시 소스 컬럼만 지정하면 자동 임베딩가장 간편한 방법
-- ai_query()를 사용한 SQL 기반 임베딩 생성
SELECT ai_query(
  'databricks-bge-large-en',  -- 임베딩 모델 엔드포인트
  text_column                  -- 임베딩할 텍스트 컬럼
) AS embedding
FROM my_catalog.my_schema.documents
참고 실무 권장: 처음 시작할 때는 Vector Search의 자동 임베딩 기능을 사용하세요. Delta 테이블의 소스 컬럼만 지정하면, 임베딩 생성부터 인덱싱까지 자동으로 처리됩니다. 이후 품질 튜닝이 필요할 때 직접 임베딩을 관리하는 방식으로 전환하세요.

다음: 임베딩으로 벡터를 만들었다면, 이제 두 벡터가 얼마나 비슷한지 측정하는 방법을 알아봅시다 → 유사도 측정