- 임베딩을 바꾸는 것은 인덱스를 다시 만드는 일입니다
- 차원과 최대 길이가 실제 설계값입니다
- 접두어를 빠뜨리면 사용법이 틀린 것입니다
- 다국어 표기와 한국어 성능은 다른 이야기입니다
- 리랭커는 임베딩과 다른 물건입니다
- MTEB 점수가 말해 주지 않는 것
- 코드 예시
- 고를 때의 순서
- 직접 해보기
- 시리즈 안내
- 참고 자료
모델 정보는 2026-08-12에 Hugging Face 페이지에서 직접 확인했습니다. 모델 카드와 라이선스는 바뀔 수 있으니 사용 전 원본을 다시 확인하세요.
임베딩을 바꾸는 것은 인덱스를 다시 만드는 일입니다
생성 모델은 언제든 교체할 수 있습니다. 임베딩 모델은 다릅니다. 바꾸는 순간 이미 저장한 모든 벡터가 무의미해지고, 원문 전체를 다시 인코딩해야 합니다. 문서가 수백만 건이면 이건 며칠짜리 작업이고, 그동안 검색 품질은 두 인덱스 사이 어딘가에 놓입니다.
그래서 임베딩 선택은 생성 모델 선택보다 훨씬 앞에서, 훨씬 신중하게 이뤄져야 합니다. 판단 근거는 리더보드 순위가 아니라 아래 네 가지 숫자와 한 가지 규약입니다.
차원과 최대 길이가 실제 설계값입니다
| 저장소 | license | 차원 | 최대 입력 | 카드에 적힌 언어 |
|---|---|---|---|---|
sentence-transformers/all-MiniLM-L6-v2 | apache-2.0 | 384 | 256 word piece 초과 시 잘림 | 영어 |
intfloat/multilingual-e5-large | mit | 1024 | 512 토큰 초과 시 잘림 | 94개 언어 |
BAAI/bge-m3 | mit | 1024 | 8192 | 100개 이상 |
Alibaba-NLP/gte-multilingual-base | apache-2.0 | 768 | 8192 | 70개 이상 |
Qwen/Qwen3-Embedding-0.6B | apache-2.0 | 최대 1024, 32에서 1024까지 지정 가능 | 32k | 100개 이상 |
Qwen/Qwen3-Embedding-8B | apache-2.0 | 최대 4096, 32에서 4096까지 지정 가능 | 32k | 100개 이상 |
차원은 품질 등급이 아니라 저장 비용과 검색 속도입니다. 문서 천만 건을 float32로 저장하면 384차원은 약 15GB, 1024차원은 약 41GB입니다. 벡터 데이터베이스 요금과 메모리 상주 여부가 여기서 갈립니다. Qwen/Qwen3-Embedding-0.6B처럼 출력 차원을 32에서 1024 사이로 지정할 수 있는 모델은 이 결정을 배포 시점으로 미룰 수 있게 해 줍니다.
최대 입력 길이는 청크 전략을 직접 결정합니다. intfloat/multilingual-e5-large 카드는 512 토큰을 넘는 텍스트가 잘린다고 명시합니다. 잘린다는 것은 오류가 나는 게 아니라 조용히 뒷부분이 사라진다는 뜻이라서, 긴 문단을 그대로 넣고 왜 검색이 안 되는지 몰라 헤매는 일이 자주 생깁니다. 반대로 BAAI/bge-m3와 Alibaba-NLP/gte-multilingual-base는 8192까지 받으므로 문서 단위 인코딩이 가능합니다.
접두어를 빠뜨리면 사용법이 틀린 것입니다
intfloat/multilingual-e5-large 카드는 모든 입력이 query 또는 passage 접두어로 시작해야 하며, 영어가 아닌 텍스트에도 마찬가지라고 적습니다. 같은 규약이 nlpai-lab/KoE5에도 그대로 적혀 있습니다. 비대칭 검색에서는 질의에 query 접두어를, 문서에 passage 접두어를 붙이라는 지시입니다.
이걸 빠뜨리면 모델은 오류 없이 벡터를 내놓고, 검색 품질만 조용히 떨어집니다. 새 임베딩 모델을 붙였는데 기대보다 나쁘다면 점수를 의심하기 전에 카드의 사용 예제를 한 글자씩 다시 읽는 편이 빠릅니다.
Qwen/Qwen3-Embedding-0.6B는 다른 형태의 규약을 씁니다. 카드는 이 모델이 지시를 인식하며 질의마다 과제를 설명하는 한 문장 지시를 함께 넣어야 한다고 적고, 지시를 쓰면 쓰지 않을 때보다 대략 1퍼센트에서 5퍼센트 개선이 있었다고 보고합니다. Alibaba-NLP/gte-multilingual-base는 사용 예제에 trust_remote_code=True가 필요하다고 적혀 있는데, 이건 품질 문제가 아니라 저장소의 코드를 실행하겠다는 승인이므로 사내 보안 정책과 부딪힐 수 있습니다.
다국어 표기와 한국어 성능은 다른 이야기입니다
100개 언어 지원이라는 문장은 그 언어의 텍스트를 처리한다는 뜻이지, 그 언어에서 잘한다는 뜻이 아닙니다. intfloat/multilingual-e5-large 카드는 자원이 적은 언어에서는 성능이 떨어질 수 있다고 직접 적습니다.
한국어를 겨냥해 추가 학습한 모델들도 있습니다.
| 저장소 | license | 기반 모델 | 차원 | 최대 입력 |
|---|---|---|---|---|
nlpai-lab/KURE-v1 | mit | BAAI/bge-m3 | 1024 | 8192 |
nlpai-lab/KoE5 | MIT | intfloat/multilingual-e5-large | 1024 | 512 |
dragonkue/BGE-m3-ko | apache-2.0 | BAAI/bge-m3 | 1024 | 8192 |
세 모델 모두 기반 모델의 차원과 최대 길이를 그대로 물려받습니다. 즉 nlpai-lab/KoE5를 쓰기로 하면 512 토큰 제약도 함께 따라옵니다. dragonkue/BGE-m3-ko 카드는 중국어와 영어 외 언어 학습이 충분하지 않아 추가 학습이 필요하다는 기반 모델 쪽 한계를 그대로 옮겨 적고, 짧은 문자열보다 긴 말뭉치에서 이점이 있다고 밝힙니다.
어느 쪽이 우리 데이터에 맞는지는 카드로 결정할 수 없습니다. 우리 문서에서 질의 100개 정도를 뽑아 정답 문서를 라벨링하고 직접 재는 것 말고 방법이 없습니다.
리랭커는 임베딩과 다른 물건입니다
임베딩은 문서를 미리 벡터로 만들어 두고 질의 벡터와 비교합니다. 리랭커는 질의와 문서를 한 쌍으로 함께 넣어 관련도 점수를 냅니다. 미리 계산해 둘 수 없으므로 전체 문서에는 쓸 수 없고, 임베딩이 좁혀 준 상위 후보에만 적용합니다.
| 저장소 | license | 형태 | 최대 길이 |
|---|---|---|---|
BAAI/bge-reranker-v2-m3 | apache-2.0 | 텍스트 분류로 분류된 리랭커, 기반 모델은 bge-m3 | 사용 예제에서 512 |
Qwen/Qwen3-Reranker-0.6B | apache-2.0 | 텍스트 리랭킹, 100개 이상 언어 | 32k |
BAAI/bge-reranker-v2-m3 카드는 출력이 관련도 점수이며 시그모이드를 거치면 0에서 1 사이 실수로 바꿀 수 있다고 적습니다. 즉 원시 출력은 확률이 아니라서 임계값을 그대로 0.5로 두면 안 됩니다. 같은 카드는 use_fp16을 켜면 계산이 빨라지는 대신 성능이 약간 떨어진다고도 밝힙니다.
MTEB 점수가 말해 주지 않는 것
Qwen/Qwen3-Embedding-8B 카드는 MTEB 다국어 부문 점수 70.58과 2025년 6월 5일 기준 1위라는 자체 보고 수치를 싣습니다. 이 문장에서 실무적으로 중요한 부분은 점수가 아니라 날짜입니다.
리더보드 순위는 시간이 지나면 바뀌고, 카드에 적힌 값은 그 시점의 스냅숏입니다. 더 근본적으로 MTEB의 과제 구성과 언어 비중은 우리 서비스의 문서 분포와 다릅니다. 사내 위키 검색과 상품 설명 검색과 법률 문서 검색은 서로 다른 문제이고, 종합 점수 한 줄로 정렬되지 않습니다.
카드에 적힌 벤치마크 수치는 배포자 자체 보고이며 독립적인 평가가 아닙니다. 이 글이 여러 임베딩 모델의 점수를 나란히 놓은 비교표를 만들지 않는 이유도 같습니다. 평가 도구와 프롬프트 규약이 다르면 같은 이름의 지표가 다른 것을 재기 때문입니다.
코드 예시
# 예시: 접두어 규약을 지켜 임베딩을 만듭니다
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("intfloat/multilingual-e5-large")
queries = ["query: 연차 이월 규정이 어떻게 되나요"]
passages = ["passage: 미사용 연차는 다음 해 3월까지 이월할 수 있습니다."]
qv = model.encode(queries, normalize_embeddings=True)
pv = model.encode(passages, normalize_embeddings=True)
print((qv @ pv.T)[0][0])
리랭커는 후보를 좁힌 뒤에만 붙입니다.
# 예시: 상위 후보에만 리랭커를 적용합니다
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3", max_length=512)
query = "연차 이월 규정"
candidates = ["미사용 연차는 다음 해 3월까지 이월됩니다.", "출장비 정산은 월말에 처리합니다."]
scores = reranker.predict([(query, c) for c in candidates])
print(sorted(zip(scores, candidates), reverse=True))
고를 때의 순서
- 문서 수와 예산으로 감당 가능한 차원 범위를 먼저 정합니다.
- 청크 길이를 정하고, 그 길이를 자르지 않는 최대 입력을 가진 모델만 남깁니다.
- 카드의 접두어 또는 지시 규약을 확인하고 그대로 구현합니다.
- 우리 문서에서 질의 100개를 뽑아 라벨링하고 후보들을 직접 비교합니다.
- 임베딩으로 상위 50개를 뽑고 리랭커로 상위 5개를 고르는 2단 구조를 기본으로 삼습니다.
직접 해보기
- ML 학습 데이터 탐색기 — 임베딩 학습 데이터의 성격이 검색 품질에 어떻게 이어지는지 살펴봅니다.
- AI 벤치마크 모음 — 벤치마크가 무엇을 재고 무엇을 재지 않는지 확인합니다.
- 브라우저 AI 실험실 — 작은 임베딩 모델을 직접 돌려 유사도 감각을 잡습니다.
시리즈 안내
- 이전 글: 텍스트 생성 오픈 모델, 크기대별로 고르는 법
- 다음 글: 한국어를 지원하는 오픈 모델과 토크나이저 비용
참고 자료
- 표의 모든 값은 2026-08-12에 해당 모델의 Hugging Face 페이지에서 직접 읽었습니다. 페이지에 없던 항목은 명시되어 있지 않음으로 적었습니다.
Qwen/Qwen3-Embedding-8B의 MTEB 수치는 카드에 실린 자체 보고 값이며 독립 평가가 아닙니다.- 라이선스 전문을 직접 읽고, 상업적 사용은 법무 검토를 거치세요.
현재 단락 (1/61)
모델 정보는 2026-08-12에 Hugging Face 페이지에서 직접 확인했습니다. 모델 카드와 라이선스는 바뀔 수 있으니 사용 전 원본을 다시 확인하세요.