WIKI임베딩·벡터검색
플레이북

임베딩·벡터검색

뜻을 좌표로 바꿔 가까운 점 찾기로 만든다.

임베딩벡터검색코사인 유사도RAG검색 기초
검색AI 입문5분

한눈에

  • 임베딩 = 뜻을 지도 위 좌표(숫자 벡터)로 바꾸기 (비슷한 뜻은 가깝게 찍힘)
  • 비슷한 뜻 찾기 = 가까운 점 찾기 (의미 비교가 거리 계산 문제로 바뀜)
  • 차원 = 좌표축 개수 (text-embedding-3-small은 숫자 1536개로 한 점을 표현)
  • 코사인 유사도 = 두 벡터 사이의 각도 (1이면 같은 방향, 0이면 무관, -1이면 정반대)
  • 벡터검색(top-k) = 질문도 점으로 찍어 가장 가까운 조각 k개 집기
  • 벡터검색 vs 키워드검색 = 뜻이 가까우면 걸림 vs 글자가 겹쳐야 걸림

모든 단어와 문장을 거대한 지도 위에 점으로 찍는다고 해보자. "강아지"와 "개"는 바로 옆에, "강아지"와 "행정소송"은 지도 반대편에. 뜻이 비슷하면 가깝게, 다르면 멀게. 임베딩이 바로 이 "뜻을 좌표로 바꾸는" 작업이다. 컴퓨터는 글자의 의미는 모르지만 좌표(숫자)의 거리는 잴 수 있다. 그래서 뜻을 좌표로 바꿔두면, "비슷한 뜻 찾기"가 "가까운 점 찾기"라는 계산 문제로 바뀐다.

임베딩, 뜻을 숫자 벡터로

임베딩(embedding)은 텍스트를 숫자 목록으로 바꾸는 것이다. "고양이" → [0.12, -0.98, 0.33, ...] 이런 식으로 수백~수천 개의 숫자가 나온다. 이 숫자 묶음(벡터)이 지도 위 좌표다. 숫자가 3개면 3차원 공간의 점이고, 1536개면 1536차원 공간의 점이다. 우리 눈엔 안 그려지지만, 거리를 재는 수학은 3차원이나 1536차원이나 똑같이 돈다.

핵심은 이 좌표를 아무렇게나 찍는 게 아니라는 것. 뜻이 비슷한 것끼리 가깝게 떨어지도록 방대한 문장으로 학습된 모델이 찍는다. 그래서 같은 뜻을 다른 단어로 써도("강아지" vs "반려견") 좌표가 서로 붙어 나온다.

비슷한 뜻 = 가까운 좌표

이 좌표계가 재밌는 건, 벡터끼리 빼고 더하는 계산이 뜻으로 말이 된다는 점이다. 가장 유명한 예시가 이거다.

왕 − 남자 + 여자 ≈ 여왕

"왕에서 남자다움을 빼고 여자다움을 더하니 여왕이 나온다." 뜻의 방향("남성→여성", "왕족다움")이 좌표의 방향으로 잡혀 있다는 얘기다. 의미가 좌표의 위치뿐 아니라 방향에까지 새겨져 있어서, 위치가 가까운지를 재면 "뜻이 얼마나 비슷한지"를 잴 수 있다.

거리는 어떻게 재나, 코사인 유사도

두 점이 얼마나 가까운지 재는 자가 필요하다. 텍스트에선 흔히 코사인 유사도를 쓴다. 원점에서 각 점으로 화살표를 긋고, 두 화살표 사이의 각도를 본다. 방향이 완전히 같으면(각 0도) 1, 직각이면 0, 정반대면 -1이다.

왜 거리(길이) 대신 방향을 볼까. 긴 글은 벡터가 길고 짧은 글은 짧게 나오는데, "무슨 얘기냐"가 같으면 길든 짧든 비슷하다고 봐야 하기 때문이다. 각도만 보면 길이 차이에 안 휘둘리고 "방향(주제)이 같은가"에 집중할 수 있다. 그래서 문서 검색에 잘 맞는다.

벡터검색, 질문도 점으로 찍어 가까운 조각 찾기

여기까지 오면 검색이 단순해진다. 문서를 미리 다 임베딩해 지도에 뿌려두고, 질문이 오면 질문도 같은 방식으로 점 하나를 찍은 뒤, 그 점에서 가장 가까운 조각 몇 개(top-k)를 집어오면 된다.

임베딩(embedding) — 텍스트를 숫자 벡터로 바꾸기. 지도에 점 찍기
차원(dimension) — 좌표축 개수. text-embedding-3-small은 숫자 1536개로 한 점을 표현
코사인 유사도 — 두 점의 방향이 얼마나 같은지. 1이면 붙어있고, 0이면 무관, -1이면 정반대
벡터검색(top-k) — 질문 점에서 가장 가까운 조각 k개를 골라오기
문서를 조각내 임베딩
미리 전부 좌표로 바꿔 지도에 뿌려둠
질문도 같은 방식으로 임베딩
질문을 지도 위 점 하나로
가장 가까운 조각 top-k
코사인 유사도로 거리를 재 상위 k개 선택
그 조각들을 근거로 답 생성
찾아온 조각을 붙여 LLM이 답을 씀 = RAG

옛날 키워드 검색과의 결정적 차이는 여기다. 키워드 검색은 글자가 겹쳐야 걸리지만, 벡터검색은 뜻이 가까우면 걸린다. "강아지 사료 추천"으로 검색해도 "반려견 먹이"라고 쓴 글이 잡힌다. DB를 다뤄봤다면 이렇게 보면 편하다. 일반 인덱스가 "정확히 일치"를 빠르게 찾아준다면, 벡터 인덱스는 "비슷한 것"을 빠르게 찾아준다.

우리 프로젝트에선

새김AI의 RAG가 정확히 이 구조로 돈다. 사용자가 쓴 게시글과 일정을 text-embedding-3-small(1536차원)로 임베딩해 지도에 뿌려두고, 질문이 오면 가까운 조각을 top-k로 끌어와 답을 만든다. 자세한 건 RAG에 정리돼 있다.

그런데 "가까운 조각을 잘 끌어오고 있나"는 눈으로 안 보인다. 그래서 saegim-eval의 검색 계층이 이 부분을 잰다. 정답 조각이 실제로 top-k 안에 들어왔는지(recall)를 채점해, 임베딩·검색이 헛다리를 짚는지 수치로 드러낸다. 임베딩은 "찍어두는 것"이고, 그게 쓸모 있으려면 "제대로 찾아오는지"를 계속 재봐야 한다.

더 읽기

지도 비유를 더 풀거나, 수식까지 들여다보는 글들.