임베딩(Embedding) 완전 이해 - 의미를 숫자로 바꾸기
컴퓨터는 "사과"와 "바나나"가 비슷하고 "사과"와 "자동차"가 다르다는 걸 어떻게 알까요? 글자만 비교하면 "사과"와 "사고"가 더 비슷해 보일 텐데 말이죠. 이 문제를 푸는 열쇠가 임베딩(Embedding) 입니다. 텍스트의 의미를 숫자 벡터로 바꿔, 의미가 비슷하면 숫자도 가깝게 만드는 기술입니다.
이 글에서는 임베딩이 무엇이고, 왜 유사도가 계산되며, 실무에서 어떻게 활용하고 무엇을 조심해야 하는지 정리합니다.
1. 임베딩은 한 문장으로
"의미가 비슷한 것끼리 가까이 모이도록, 텍스트를 좌표(벡터)로 바꾸는 것."
임베딩 모델에 문장을 넣으면 고정 길이의 숫자 배열이 나옵니다.
const v = await embed("결제를 취소하고 싶어요");
// => [0.021, -0.135, 0.008, 0.240, ... ] (예: 1536개의 숫자)
이 숫자 하나하나에 사람이 이해할 이름표가 붙어 있진 않습니다. 대신 전체 벡터가 하나의 "의미 좌표" 를 이룹니다. 핵심 성질은 이것입니다.
- "결제 취소하는 법"과 "환불 요청 방법"은 → 벡터가 가깝다
- "결제 취소하는 법"과 "오늘 점심 메뉴"는 → 벡터가 멀다
단어가 달라도 의미가 통하면 가까이 놓인다는 게 핵심입니다. 이래서 키워드 검색으로는 못 잡는 "뜻이 같은 다른 표현"을 잡아낼 수 있습니다.
2. 벡터 공간이라는 지도
임베딩을 이해하는 가장 좋은 비유는 지도 입니다. 세상의 모든 개념을 아주 고차원(수백~수천 차원) 공간의 점으로 찍은 지도라고 상상해보세요.
- 가까운 점 = 의미가 비슷한 것
- 먼 점 = 의미가 다른 것
유명한 예로, 잘 학습된 벡터 공간에서는 이런 "방향"도 의미를 가집니다.
왕(king) - 남자(man) + 여자(woman) ≈ 여왕(queen)
"성별을 바꾸는 방향"이라는 게 벡터의 뺄셈·덧셈으로 표현된다는 뜻입니다. 물론 실제 문장 임베딩이 이렇게 딱 떨어지진 않지만, 의미가 기하학적 위치·방향으로 표현된다는 직관을 주기엔 충분합니다.
우리 눈은 3차원까지밖에 못 보지만, 임베딩은 보통 수백~수천 차원을 씁니다. 차원이 많을수록 더 미묘한 의미 차이를 담을 수 있습니다.
3. 유사도는 어떻게 재는가 - 코사인 유사도
두 벡터가 얼마나 비슷한지 재는 대표 방법이 코사인 유사도(Cosine Similarity) 입니다. 두 벡터가 이루는 각도를 봅니다.
- 같은 방향(각도 0°) → 유사도 1 (매우 비슷)
- 직각(90°) → 유사도 0 (무관)
- 반대 방향(180°) → 유사도 -1 (반대)
import numpy as np
def cosine(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
cosine(embed("환불 방법"), embed("결제 취소"))
cosine(embed(), embed())