임베딩(Embedding) 완벽 가이드: 개념부터 FAISS 검색까지 끝내기

임베딩(Embedding)의 개념부터 FAISS 검색까지 살펴봅니다.

.

2026. 2. 24  최초작성

.

.

임베딩(Embedding) 완벽 가이드: 개념부터 FAISS 검색까지 끝내기

.

.

1. 임베딩이란?

임베딩은 인간이 사용하는 자연어(텍스트)를 컴퓨터가 이해하고 연산할 수 있는 고차원 실수 벡터(dense vector)로 변환하는 기술입니다.  단어, 문장, 문서 등 다양한 단위의 텍스트를 사용하는 모델에 따라 수백에서 수천 차원의 숫자 배열로 표현하며, 이 과정에서 의미적 정보가 벡터 공간에 인코딩됩니다. 

예를 들어, “고양이”라는 단어는 [0.12, -0.34, 0.78, …, 0.56]과 같은 고차원 벡터로 변환됩니다.  이때 벡터의 차원은 사용하는 임베딩 모델에 따라 달라집니다. BERT 계열은 768차원, OpenAI의 text-embedding-3-large는 최대 3072차원, BGE-M3는 1024차원 등 모델마다 출력 차원이 다르며, 이는 표현력과 저장·연산 비용 간의 트레이드오프에 영향을 줍니다.  “강아지”의 벡터는 “고양이”와 가까운 위치에, “자동차”의 벡터는 먼 위치에 배치됩니다. 

.

1.1. 직관적 비유

지도 위에 도시를 배치하는 것과 유사합니다.  서울과 인천은 지도에서 가깝고, 서울과 뉴욕은 멀리 배치됩니다.  임베딩은 의미의 지도를 만드는 것입니다.  비슷한 뜻을 가진 단어나 문장은 벡터 공간에서 가까이 위치하고, 관련 없는 것들은 멀리 위치하게 됩니다.

.

.

2. 임베딩의 핵심 원리

2.1. 분포 가설 (Distributional Hypothesis)

임베딩의 이론적 토대는 “비슷한 문맥에서 등장하는 단어는 비슷한 의미를 가진다”는 분포 가설입니다. 예를 들어 “커피를 ___다”와 “차를 ___다”에서 빈칸에는 “마시다”, “끓이다”, “타다”, “내리다” 등의 단어가 공통으로 들어갈 수 있습니다. 이처럼 동일한 문맥 패턴을 공유하기 때문에 모델은 “커피”와 “차”가 의미적으로 가까운 단어라고 학습하게 됩니다.

.

2.2. 학습 과정

딥러닝 기반 임베딩 모델은 대규모 텍스트 코퍼스에서 다음과 같은 방식으로 학습합니다. 여기에서는 두가지를 살펴봅니다.

.

자기지도 학습(Self-supervised Learning): 별도의 레이블 없이 텍스트 자체의 구조를 학습 신호로 활용합니다. 예를 들어 BERT 계열 모델은 문장에서 일부 토큰을 마스킹하고 이를 예측하는 과제(Masked Language Modeling)를 통해 문맥 이해 능력을 습득합니다. 

.

원본 문장:  “오늘 서울의 날씨는 매우 맑다”

마스킹 입력: “오늘 서울의 [MASK]는 매우 [MASK]”

모델 예측:   [MASK] → “날씨”,  [MASK] → “맑다”

.

모델은 주변 문맥(“오늘”, “서울의”, “매우”)을 통해 가려진 단어를 예측하는 과정을 수억 개의 문장에 대해 반복하며, 자연스럽게 단어와 문맥 사이의 의미 관계를 벡터에 담아내게 됩니다. 

.
.

대조 학습(Contrastive Learning): 의미적으로 유사한 문장 쌍(positive pair)은 벡터 공간에서 가까워지도록, 관련 없는 문장 쌍(negative pair)은 멀어지도록 학습합니다.

.

Positive Pair (유사 → 가깝게 학습):

  문장 A: “강아지가 공원에서 뛰어놀고 있다”

  문장 B: “반려견이 공원에서 달리며 놀고 있다”

  → 벡터 유사도를 높이는 방향으로 학습

.

Negative Pair (비유사 → 멀게 학습):

  문장 A: “강아지가 공원에서 뛰어놀고 있다”

  문장 C: “주식 시장이 오늘 큰 폭으로 하락했다”

  → 벡터 유사도를 낮추는 방향으로 학습

.

이 과정을 반복하면 모델은 표면적인 단어가 달라도 의미가 같으면 가까운 벡터를, 단어가 겹치더라도 의미가 다르면 먼 벡터를 생성하게 됩니다. 이 방식은 문장 임베딩 품질을 크게 향상시킵니다.

.

2.3. 벡터 공간의 수학적 성질

잘 학습된 임베딩 공간에서는 벡터 연산이 의미 연산에 대응합니다. 

vec(“왕”) – vec(“남자”) + vec(“여자”) ≈ vec(“여왕”)

vec(“서울”) – vec(“한국”) + vec(“일본”) ≈ vec(“도쿄”)

.

2.4. 유사도 측정 방법 비교

두 벡터가 얼마나 비슷한지를 측정하는 방법은 여러 가지가 있습니다. 각 방법의 특징을 이해하면 상황에 맞는 선택을 할 수 있습니다.

.

코사인 유사도 (Cosine Similarity): 두 벡터가 이루는 각도를 기반으로 유사도를 측정한다. 벡터의 크기(길이)는 무시하고 방향만 비교합니다. -1~1 사이의 값을 가지며, 임베딩 검색에서 가장 널리 사용됩니다.

cosine_similarity(A, B) = (A · B) / (||A|| × ||B||)

.

유클리드 거리 (Euclidean Distance, L2): 두 벡터 사이의 직선 거리를 측정합니다. 값이 0에 가까울수록 유사합니다. 벡터의 크기에 영향을 받으므로, 정규화하지 않은 벡터에서는 결과가 왜곡될 수 있습니다.

euclidean_distance(A, B) = √(Σ(Aᵢ – Bᵢ)²)

.

내적 (Dot Product / Inner Product): 두 벡터를 내적한 값. 벡터가 정규화(L2 norm = 1)되어 있으면 코사인 유사도와 동일한 결과를 반환합니다. FAISS에서 IndexFlatIP를 사용할 때 벡터를 정규화하는 이유가 바로 이것입니다.

dot_product(A, B) = Σ(Aᵢ × Bᵢ)

.

방법값의 범위유사할 때특징사용 시점
코사인 유사도-1 ~ 11에 가까움방향만 비교, 크기 무시임베딩 검색의 기본 선택
유클리드 거리0 ~ ∞0에 가까움절대적 거리 측정클러스터링, 이상 탐지
내적-∞ ~ ∞값이 클수록정규화 시 코사인과 동일FAISS 등 최적화된 검색

벡터를 정규화한 후 내적을 사용하는 것이 가장 일반적인데 왜냐면 코사인 유사도와 결과가 같으면서, 내적 연산이 더 빠르기 때문입니다. 

.

.

3. 임베딩이 필요한 이유

3.1. 컴퓨터의 근본적 한계 극복

컴퓨터는 숫자만 처리할 수 있습니다. “오늘 날씨가 좋다”라는 문장을 그대로는 연산할 수 없으므로, 수치적 표현으로의 변환이 필수적입니다. 과거에는 원-핫 인코딩(One-hot Encoding)을 사용했지만, 이는 단어 간 의미적 관계를 전혀 반영하지 못하고 차원이 어휘 크기에 비례하여 폭발적으로 증가하는 문제가 있었습니다.

.

[원-핫 인코딩 예시] 어휘: {고양이, 강아지, 자동차, 비행기}

.

고양이 = [1, 0, 0, 0]

강아지 = [0, 1, 0, 0]

자동차 = [0, 0, 1, 0]

비행기 = [0, 0, 0, 1]

.

문제점:

– “고양이”와 “강아지”의 코사인 유사도 = 0 (의미가 비슷한데 전혀 관련 없다고 나옴)

– “고양이”와 “자동차”의 코사인 유사도 = 0 (위와 동일, 구분 불가)

– 어휘가 10만 개면 벡터 차원도 10만 → 메모리 낭비가 심각

.

.

[임베딩 예시] 동일 단어를 3차원 임베딩으로 표현 (실제로는 768차원 이상)

.

고양이 = [0.82, 0.31, -0.15]

강아지 = [0.79, 0.35, -0.12]   ← 고양이와 유사한 수치라  고양이와 매우 가까움!

자동차 = [-0.21, 0.68, 0.55]   ← 고양이와 차이나는 수치라 고양이와 멀리 떨어짐

비행기 = [-0.18, 0.71, 0.62]   ← 자동차와 유사한 수치라 자동차와 가까움 (둘 다 탈것)

.

임베딩은 이처럼 적은 차원으로도 단어 간 의미 관계를 수치적으로 표현할 수 있어, 원-핫 인코딩의 문제를 근본적으로 해결합니다.

.

.

3.2. Sparse vs. Dense: 키워드 검색의 한계

임베딩을 이해하려면, 그 이전에 사용되던 희소 표현(Sparse Representation)과 비교하는 것이 도움이 됩니다.

.

Sparse 방식 (TF-IDF, BM25): 문서에 등장하는 단어의 빈도를 기반으로 벡터를 만듭니다. 어휘가 10만 개면 벡터도 10만 차원이며, 대부분의 값이 0입니다(그래서 “희소”라고 부릅니다). 키워드가 정확히 일치해야 검색되므로, “강아지 산책”으로 “반려견 외출”을 찾을 수 없습니다. 반면 정확한 키워드 매칭에는 매우 강하고, 연산이 빠릅니다.

.

Dense 방식 (딥러닝 임베딩): 이 문서에서 다루는 임베딩이 바로 Dense 방식입니다. 모든 차원에 의미 있는 값이 들어 있는 768~3072차원의 “밀집” 벡터를 생성합니다. 키워드가 달라도 의미가 비슷하면 높은 유사도를 보이지만 고유명사나 코드명 같은 정확한 매칭에는 오히려 약할 수 있습니다.

.

검색 쿼리: “삼성전자 2024년 4분기 실적”

.

Sparse (BM25):  “삼성전자”, “2024년”, “4분기”, “실적” 키워드가 포함된 문서 검색

                → 정확한 키워드 매칭에 강함
.

Dense (임베딩):  쿼리의 의미와 비슷한 벡터를 가진 문서 검색

                → “삼성전자 Q4 실적 발표” 등 표현이 달라도 검색 가능

                → 하지만 “삼성전자”를 “LG전자”로 혼동할 가능성도 있음

.

현재 가장 좋은 성능을 내는 검색 시스템은 두 방식을 결합한 하이브리드 검색을 사용합니다.

.

3.3. 의미 기반 검색(Semantic Search)

키워드 매칭 방식의 전통적 검색은 “강아지 산책 방법”이라는 질문에 “반려견 외출 가이드”라는 문서를 찾지 못합니다. 임베딩 기반 검색은 의미적 유사성을 계산하므로, 표현이 달라도 뜻이 통하면 검색 결과로 반환할 수 있습니다.

.

3.4. RAG(Retrieval-Augmented Generation)의 핵심 인프라

대규모 언어 모델(LLM)의 환각(Hallucination) 문제를 해결하기 위한 RAG 파이프라인에서 임베딩은 핵심 역할을 한다. 환각이란 LLM이 사실이 아닌 내용을 마치 사실인 것처럼 그럴듯하게 생성하는 현상을 말합니다. 예를 들어, “한국 최초의 우주비행사는 누구인가?”라는 질문에 존재하지 않는 인물 이름을 자신 있게 답하는 경우가 이에 해당합니다. RAG는 사용자 질문을 임베딩하고, 사전에 임베딩해 둔 문서 청크들과 유사도를 비교하여 가장 관련성 높은 문서를 LLM에 컨텍스트로 제공함으로써 이 문제를 완화합니다.

.

자세한 내용은 다음 포스트를 참고하세요.

.

RAG(Retrieval-Augmented Generation) 개념 및 구현

.

3.5. 다양한 다운스트림 태스크 지원

임베딩 벡터는 텍스트 분류, 감성 분석, 문서 클러스터링, 추천 시스템, 중복 문서 탐지, 질의응답 등 거의 모든 NLP 태스크의 입력으로 활용됩니다. 한 번 잘 만든 임베딩은 여러 태스크에 재사용할 수 있어 효율적입니다.

.

3.6. 차원 축소와 효율성

어휘가 10만 개라면 원-핫 벡터는 10만 차원이 필요하지만, 임베딩은 768~1536 차원 정도로 풍부한 의미 정보를 압축합니다. 저장 공간과 연산 비용이 크게 절감됩니다.

.

.

4. FAISS를 사용하는 이유

4.1. FAISS란?

FAISS(Facebook AI Similarity Search)는 Meta(구 Facebook) AI Research에서 개발한 고효율 벡터 유사도 검색 라이브러리입니다. 대규모 벡터 집합에서 주어진 쿼리 벡터와 가장 유사한 벡터를 빠르게 찾아주는 것이 핵심 기능입니다.

.

4.2. 왜 FAISS가 필요한가?

브루트포스 검색의 한계: 100만 개의 문서 벡터(768차원)가 있을 때, 쿼리 하나에 대해 모든 벡터와의 코사인 유사도를 계산하면 약 7억 6,800만 번의 곱셈이 필요합니다. 문서가 1억 개면 실시간 응답이 불가능합니다.

.

FAISS는 이 문제를 근사 최근접 이웃 탐색(ANN, Approximate Nearest Neighbor) 알고리즘으로 해결합니다. 100% 정확하지는 않지만, 99% 이상의 정확도로 수천 배 빠른 검색을 가능하게 합니다.

.

4.3. FAISS의 핵심 장점

압도적인 속도: 수억 개의 벡터에서도 밀리초 단위로 유사 벡터를 검색합니다. 내부적으로 IVF(Inverted File Index), HNSW(Hierarchical Navigable Small World), PQ(Product Quantization) 등 다양한 인덱싱 알고리즘을 조합하여 속도를 최적화합니다.

GPU 가속 지원: CUDA를 통한 GPU 연산을 네이티브로 지원하여, CPU 대비 수십 배 빠른 검색이 가능합니다. 대규모 서비스에서 큰 이점입니다.

메모리 효율성: PQ(Product Quantization), SQ(Scalar Quantization) 등의 압축 기법으로 벡터를 원본 대비 수십 분의 1로 압축하면서도 검색 정확도를 유지합니다. 예를 들어 768차원 float32 벡터(3KB)를 64바이트로 압축할 수 있습니다.

검증된 안정성: Meta 내부의 대규모 프로덕션 환경에서 수년간 검증되었으며, 전 세계적으로 가장 널리 사용되는 벡터 검색 라이브러리입니다.

유연한 인덱스 구성: 정확도, 속도, 메모리 사용량 간의 트레이드오프를 세밀하게 조절할 수 있습니다.

.

4.4. 주요 인덱스 유형

인덱스특징적합한 상황
IndexFlatL2 / IndexFlatIP정확한 브루트포스 검색소규모 데이터(~10만 건), 정확도 최우선
IndexIVFFlat클러스터 기반 탐색으로 검색 범위 축소중규모 데이터(~1,000만 건)
IndexIVFPQIVF + Product Quantization 압축대규모 데이터(~1억 건), 메모리 제한 환경
IndexHNSWFlat그래프 기반 탐색, 높은 재현율높은 정확도가 필요한 중규모 데이터

.

4.5. FAISS 기본 사용 예시

필요한 패키지를 설치해야 합니다. 

pip install sentence-transformers faiss-cpu

import os
import warnings

os.environ[“HF_HUB_DISABLE_PROGRESS_BARS”] = “1”
os.environ[“HF_HUB_DISABLE_TELEMETRY”] = “1”
os.environ[“HF_HUB_DISABLE_IMPLICIT_TOKEN”] = “1”
os.environ[“TOKENIZERS_PARALLELISM”] = “false”
os.environ[“TRANSFORMERS_VERBOSITY”] = “error”
warnings.filterwarnings(“ignore”)

import logging
logging.disable(logging.WARNING)
logging.getLogger(“sentence_transformers”).setLevel(logging.ERROR)
logging.getLogger(“transformers”).setLevel(logging.ERROR)
logging.getLogger(“huggingface_hub”).setLevel(logging.ERROR)

import faiss
from sentence_transformers import SentenceTransformer

# 1. 임베딩 모델 로드 (한국어 검색 벤치마크 8개 전체 1위)
model = SentenceTransformer(“nlpai-lab/KURE-v1”)

# 2. 문서 데이터베이스 (서로 다른 분야의 예문 – 검색 의미가 명확하도록 보강)
documents = [
    # 요리/음식
    “김치찌개는 돼지고기와 김치를 넣고 끓이는 한국의 대표적인 가정식 요리입니다.”,
    “파스타는 이탈리아 면 요리로, 토마토 소스나 크림 소스와 함께 먹습니다.”,
    “빵은 밀가루 반죽을 발효시켜 오븐에 굽는 음식으로 아침 식사로 인기 있습니다.”,
    # 운동/다이어트
    “달리기는 체지방을 태우는 유산소 운동으로 다이어트에 효과적입니다.”,
    “스쿼트는 하체 근력을 키우는 근력 운동으로 기초대사량을 높여줍니다.”,
    “수영은 전신 운동으로 칼로리 소모가 크고 관절에 부담이 적습니다.”,
    # 여행
    “해외여행 시 여권과 비자를 반드시 준비해야 하며 유효기간을 확인해야 합니다.”,
    “유럽 배낭여행에서는 유레일 패스로 여러 나라의 기차를 자유롭게 탈 수 있습니다.”,
    “비행기 예약은 출발 2~3개월 전에 하면 항공권을 저렴하게 구매할 수 있습니다.”,
    # 금융/재테크
    “주식 투자는 기업의 지분을 사고팔아 시세 차익으로 돈을 버는 재테크 방법입니다.”,
    “적금은 매달 일정 금액을 은행에 저축하고 만기에 원금과 이자를 받는 저축 상품입니다.”,
    “부동산 투자는 아파트나 토지를 매입하여 시세 상승이나 임대 수입을 얻는 방법입니다.”,
    # 반려동물
    “강아지를 키울 때는 매일 산책시키고 정기적으로 예방접종을 해야 합니다.”,
    “고양이는 하루 16시간 이상 잠을 자며 독립적인 성격을 가진 반려동물입니다.”,
    “열대어를 키우려면 수조의 수온과 수질을 꾸준히 관리해야 합니다.”,
]

# 3. 문서를 임베딩 벡터로 변환
print(“문서 임베딩 생성 중…”)
doc_embeddings = model.encode(documents, convert_to_numpy=True).astype(“float32”)
dimension = doc_embeddings.shape[1]

# 4. FAISS 인덱스 생성 (코사인 유사도)
index = faiss.IndexFlatIP(dimension)
faiss.normalize_L2(doc_embeddings)
index.add(doc_embeddings)

print(f”인덱스에 {index.ntotal}개 문서 등록 완료 (벡터 차원: {dimension})”)

# 5. 검색 쿼리 (문서에 없는 표현으로 의미 검색 테스트)
queries = [
    “저녁에 뭐 해먹지?”,
    “살 빼는 운동 추천해줘”,
    “해외여행 준비물이 뭐야?”,
    “돈을 불리는 방법 알려줘”,
    “우리 집 고양이가 너무 많이 자요”,
]

THRESHOLD = 0.35  # 유사도 임계값

print(“\n” + “=” * 60)
k = 3

for query in queries:
    query_embedding = model.encode([query], convert_to_numpy=True).astype(“float32”)
    faiss.normalize_L2(query_embedding)
    distances, indices = index.search(query_embedding, k=k)

    print(f”\n[쿼리] {query}”)
    print(“-” * 40)
    for rank, (idx, score) in enumerate(zip(indices[0], distances[0]), 1):
        if score >= THRESHOLD:
            print(f”  {rank}. (유사도: {score:.4f}) {documents[idx]}”)
        else:
            print(f”  {rank}. (유사도: {score:.4f}) [관련도 낮음 – 제외]”)

print(“\n” + “=” * 60)

.

실행결과

문서 임베딩 생성 중…
인덱스에 15개 문서 등록 완료 (벡터 차원: 1024)

============================================================

[쿼리] 저녁에 뭐 해먹지?
—————————————-
  1. (유사도: 0.5090) 빵은 밀가루 반죽을 발효시켜 오븐에 굽는 음식으로 아침 식사로 인기 있습니다.
  2. (유사도: 0.5035) 파스타는 이탈리아 면 요리로, 토마토 소스나 크림 소스와 함께 먹습니다.
  3. (유사도: 0.4879) 김치찌개는 돼지고기와 김치를 넣고 끓이는 한국의 대표적인 가정식 요리입니다.

[쿼리] 살 빼는 운동 추천해줘
—————————————-
  1. (유사도: 0.5951) 달리기는 체지방을 태우는 유산소 운동으로 다이어트에 효과적입니다.
  2. (유사도: 0.5744) 수영은 전신 운동으로 칼로리 소모가 크고 관절에 부담이 적습니다.
  3. (유사도: 0.5469) 스쿼트는 하체 근력을 키우는 근력 운동으로 기초대사량을 높여줍니다.

[쿼리] 해외여행 준비물이 뭐야?
—————————————-
  1. (유사도: 0.6255) 해외여행 시 여권과 비자를 반드시 준비해야 하며 유효기간을 확인해야 합니다.
  2. (유사도: 0.4820) 유럽 배낭여행에서는 유레일 패스로 여러 나라의 기차를 자유롭게 탈 수 있습니다.
  3. (유사도: 0.4634) 비행기 예약은 출발 2~3개월 전에 하면 항공권을 저렴하게 구매할 수 있습니다.

[쿼리] 돈을 불리는 방법 알려줘
—————————————-
  1. (유사도: 0.4948) 부동산 투자는 아파트나 토지를 매입하여 시세 상승이나 임대 수입을 얻는 방법입니다.
  2. (유사도: 0.4301) 적금은 매달 일정 금액을 은행에 저축하고 만기에 원금과 이자를 받는 저축 상품입니다.
  3. (유사도: 0.4276) 주식 투자는 기업의 지분을 사고팔아 시세 차익으로 돈을 버는 재테크 방법입니다.

[쿼리] 우리 집 고양이가 너무 많이 자요
—————————————-
  1. (유사도: 0.7043) 고양이는 하루 16시간 이상 잠을 자며 독립적인 성격을 가진 반려동물입니다.
  2. (유사도: 0.4816) 강아지를 키울 때는 매일 산책시키고 정기적으로 예방접종을 해야 합니다.
  3. (유사도: 0.3832) 수영은 전신 운동으로 칼로리 소모가 크고 관절에 부담이 적습니다.

============================================================

.

현재 결과가 완벽하지 않은 이유:                                                                                                                                                                                                                                                                                                                       

  – 임베딩 모델은 문장을 하나의 벡터로 압축하기 때문에 세밀한 의미 구분에 한계가 있음

  – “고양이가 많이 자요”와 “수영” 사이에 직접적 관련은 없지만, 벡터 공간에서 우연히 가까운 위치에 배치됨                                                                                                                                                                                                                                    

  – 유사도 최고점이 0.70 수준인 것 자체가 모델의 표현력 한계를 보여줌                                                                                                                                                                                                                                                                     

 이렇게 보완할 수 있습니다.

  1. Re-ranker 추가 — FAISS로 후보 10개를 먼저 뽑고, Cross-Encoder 모델로 정밀 재정렬

  2. 하이브리드 검색 — 임베딩 검색 + 키워드 검색(BM25)을 결합

  3. 임계값 필터 — 현재 적용한 것처럼 낮은 점수 결과를 제거. 임계값을 조정하면 위 결과가 개선됩니다. 

.

.

5. 자주 묻는 질문 (FAQ)

Q1. 임베딩 벡터의 각 숫자(차원)는 각각 무슨 의미인가요?

명확한 의미가 없다. 예를 들어 “768차원 중 123번째 값이 감정을 나타낸다”와 같이 해석할 수 없다. 각 차원은 학습 과정에서 자동으로 결정된 추상적인 특징이며, 개별 값보다는 벡터 전체가 모여서 하나의 의미를 표현한다. 이것이 임베딩을 “분산 표현(Distributed Representation)”이라고도 부르는 이유다.

.

Q2. 차원이 높을수록 무조건 좋은 건가요?

그렇지 않다. 차원이 높으면 더 세밀한 의미를 담을 수 있지만, 저장 공간과 검색 시간이 비례하여 증가한다. 또한 학습 데이터가 부족하면 고차원에서 오히려 성능이 떨어질 수 있다(차원의 저주). 실무에서는 768~1024차원이 가장 보편적이며, 특별한 이유가 없다면 모델의 기본 차원을 그대로 사용하면 된다.

.

Q3. 임베딩은 한 번만 만들면 영구적으로 쓸 수 있나요?

원칙적으로는 그렇다. 하지만 모델을 변경하면 기존 임베딩을 모두 다시 생성해야 한다. 또한 문서가 추가·수정·삭제되면 해당 부분의 임베딩도 갱신해야 한다. 따라서 임베딩 생성 파이프라인을 자동화해 두는 것이 좋다.

.

Q4. OpenAI API로 임베딩을 만드는 것과 직접 모델을 돌리는 것의 차이는?

방식장점단점
API (OpenAI, Cohere 등)설치·관리 불필요, 코드 간단, 높은 성능비용 발생, 데이터가 외부 서버로 전송됨, 인터넷 필요
로컬 모델 (sentence-transformers 등)무료, 데이터 외부 유출 없음, 오프라인 사용 가능GPU 필요(권장), 모델 다운로드·관리 필요

개인 프로젝트나 프로토타입에는 API가 편리하고, 데이터 보안이 중요하거나 대량 처리가 필요하면 로컬 모델이 유리하다.

.

Q5. 이미지나 오디오도 임베딩할 수 있나요?

가능하다. CLIP(OpenAI)은 이미지와 텍스트를 동일한 벡터 공간에 임베딩하여, 텍스트로 이미지를 검색하거나 그 반대가 가능하다. 오디오도 Whisper 등의 모델로 임베딩할 수 있다. 이처럼 서로 다른 종류의 데이터를 같은 공간에 임베딩하는 것을 멀티모달 임베딩(Multimodal Embedding)이라고 한다.

.

Q6. FAISS 인덱스를 저장하고 나중에 다시 불러올 수 있나요?

가능하다. faiss.write_index()와 faiss.read_index()를 사용하면 된다.

# 저장
faiss.write_index(index, “my_index.faiss”)

# 불러오기
index = faiss.read_index(“my_index.faiss”)

서비스 운영 시에는 임베딩 생성과 인덱스 로드를 분리하여, 서버 시작 시 미리 만들어둔 인덱스를 불러오는 방식으로 구성한다.

.

Q7. 한국어만 다룬다면 다국어 모델 대신 한국어 전용 모델이 항상 좋은가요?

반드시 그렇지는 않다. 최근 다국어 모델(multilingual-e5, BGE-M3 등)은 한국어 전용 모델과 동등하거나 더 높은 성능을 보이는 경우가 많다. 선택 시에는 자신의 실제 데이터로 직접 테스트하는 것이 가장 확실하다. 소규모 테스트 세트(쿼리 50~100개 + 정답 문서)를 만들어 모델별 검색 정확도를 비교해 보는 것을 권장한다.

.

.

댓글 남기기