결론 한 줄
- 벡터화: 데이터를 숫자 배열(벡터)로 바꾸는 것(넓은 개념)
- 임베딩: 그 벡터가 “의미가 비슷하면 가깝게” 배치되도록 만든(학습된) 벡터 표현
- 유사도 검색: 질문 벡터와 문서 벡터들 중 가장 가까운 것(Top‑K) 을 찾는 것
벡터란? (좌표로 생각하기)
벡터는 그냥 이렇게 생긴 숫자 리스트야.
- 2차원: ((x, y)) → 평면의 점
- 3차원: ((x, y, z)) → 공간의 점
- N차원: ((x_1, x_2, …, x_N)) → “상상은 어렵지만” 수학은 똑같이 되는 점
핵심 아이디어는 이것:
문장을 점(벡터)로 만들면,
점끼리의 가까움(거리/각도) 으로 “비슷함”을 숫자로 계산할 수 있다.
벡터화(Vectorization)란?
질문:
“벡터화한다는 것은 N차원 공간으로 데이터를 표현하는 것이지?”
대답은 맞아.
벡터화는 텍스트 같은 걸 N개의 숫자로 표현하는 것 전체를 말해.
그런데 “벡터화”에는 종류가 많아. 대표적으로:
- Bag-of-Words(단어 등장 횟수)
- TF‑IDF(정보량 가중치)
- Neural Embedding(딥러닝 임베딩) ← 이게 우리가 말하는 “임베딩”과 가장 가까움
3) 단어 기반 벡터화 예시
(A) Bag-of-Words(단어 등장 횟수)
단어 사전(어휘)을 미리 정하고, 각 단어를 축(차원)으로 만들어.
예를 들어 어휘가 5개라고 해보자.
- 어휘: ([환불, 배송, 지연, 비밀번호, 재설정])
문장 S1: “환불 환불”
→ 벡터: ([2, 0, 0, 0, 0])
문장 S2: “배송 지연”
→ 벡터: ([0, 1, 1, 0, 0])
단어 기반 벡터화의 한계
질문:
“그렇게 의미가 표현되어 있기 때문에 기존에 단어 맵핑으로 검색하면 찾을 수 없었던 데이터를 의미로 근처에 있는 데이터를 찾는 방식으로 찾기 때문에 검색이 더 유의미하다는 것인가?”
포인트는 이거야:
- Bag-of-Words/키워드 검색은 “같은 단어가 있나?”를 크게 본다.
- 그래서 표현이 달라지면(동의어/패러프레이즈) 놓칠 수 있다.
예를 들어:
- Q: “결제 취소 언제까지?”
- D: “환불은 7일 이내”
사람은 취소/환불이 비슷하다고 느끼지만,
단어 기반 벡터화는 “취소”와 “환불”이 다른 축이면 가까움을 잘 못 잡을 수 있다.
4) 임베딩(Embedding)이란?
질문:
“벡터화한다는 것은 N차원 공간으로 데이터를 표현하는 것이고, 그것에 의미/관계를 거리로 표현하도록 만드는 것을 임베딩이라고 하는거지?”
거의 정답이고, 더 정확히는 이거야:
임베딩은 입력(문장/문단 등)을 dense 실수 벡터로 바꾸되,
의미가 비슷한 입력은 가까운 벡터가 되도록 학습된 표현이다.
중요한 포인트: ‘환불축’ 같은 차원은 보통 사람이 해석 못 함
임베딩 차원 하나하나는 보통 “환불축/배송축”처럼 이름이 붙어 있지 않아.
대신 의미가 여러 차원에 분산(distributed) 되어 표현돼.
그래서 예전에 들었던 (q=(1,0,1)) 같은 값은 “설명용 장난감”이고,
실제 임베딩은 수백~수천 차원에 실수 값이 잔뜩 나오는 형태야.
5) 텍스트를 “임베딩 벡터”로 만드는 과정(원리/흐름)
질문:
“그렇다면 질문, 문서 A를 어떻게 저 벡터로 만들었는지가 궁금해.”
대부분의 현대 임베딩은 Transformer 계열을 쓴다고 보면 돼. 흐름은 이렇게 단순해:
(1) 토크나이즈: 문장을 조각(토큰)으로 쪼갬
예: “결제 취소 언제까지?” → ([결, 제, 취, 소, …]) 같은 서브워드 토큰들
(2) 토큰을 숫자 벡터로 바꿈 (토큰 임베딩)
각 토큰마다 “처음부터 숫자 벡터”가 있어. (단어사전처럼)
(3) Transformer가 문맥을 섞어서 “문맥 벡터”로 바꿈
여기서 핵심: 같은 단어라도 문맥에 따라 표현이 바뀌게 됨.
- “취소”가 “환불/결제” 맥락에 있으면 그쪽 의미가 강해지고
- “구독 취소” 맥락이면 또 달라져
(4) 문장 전체를 대표하는 벡터 1개로 “풀링(pooling)”
토큰이 여러 개니까, 문장 하나를 벡터 하나로 만들기 위해 평균(mean pooling) 같은 걸 함.
이 과정은 Sentence-Transformers 문서에서 (Transformer → Pooling → (선택) Normalize) 같은 구성으로 설명돼.
즉, “문장을 벡터로 만든다”는 건 대충
토큰 벡터들(많음) → 문맥 반영 → 평균/대표값으로 하나로 합치기
라고 보면 돼.
6) “의미적으로 가깝다”는 건 수학적으로 어떻게 확인하나?
가장 흔한 방식은 코사인 유사도(cosine similarity) 야.
[ \text{cos_sim}(x,y) = \frac{x\cdot y}{|x|,|y|} ]
- (x\cdot y) : 내적(각 성분끼리 곱해서 더함)
- (|x|) : 벡터 길이(정규화)
직관
- 방향이 비슷하면 1에 가까움(매우 유사)
- 관계 없으면 0 근처
- 반대 의미면 -1 근처(실무에선 자주 보진 않음)
7) “질문 벡터와 가장 가까운 벡터를 찾는다”는 건 구체적으로 뭐야?
벡터 DB(또는 라이브러리)는 이런 문제를 푼다:
- 문서 벡터들이 (x_1, x_2, …, x_n) 저장돼 있고
- 새 질문 벡터가 (q) 로 들어오면
- 가장 가까운 Top‑K 를 찾는다 (nearest neighbor search)
가까움 기준은 보통:
- 코사인 유사도(= 정규화된 내적)
- 내적(dot product)
- L2 거리(유클리드 거리)
8) “가장 가까운 벡터”는 ‘비슷한 질문’을 찾는 건가?
질문:
“사용자가 자연어로 질의 했을 때 해당 질의와 가장 비슷한 질문을 DB에서 찾고 그후 답변을 찾는 방법인거야?”
가능한 구조이긴 한데, RAG에서 가장 흔한 기본형은 약간 달라.
(A) FAQ형(비슷한 질문 찾기)
- DB에 (질문, 답변) 쌍이 있고
- “질문들”을 임베딩으로 저장해둔 뒤
- 사용자 질문과 가장 비슷한 질문을 찾아 그 답변을 준다
→ 이건 “Q→A 검색 시스템”에 가깝다.
(B) RAG 기본형(비슷한 ‘문서 조각’ 찾기) — 더 흔함
- DB에는 “질문”이 아니라 문서 조각(chunk) 을 저장한다
- 사용자 질문 임베딩과 가까운 문서 조각 Top‑K 를 가져온다
- 그 조각들을 LLM에게 “근거(context)”로 제공해서 답을 만든다
→ 이게 흔히 말하는 RAG(Search→Ask) 흐름.
9) 요약 (질문 흐름으로 다시 연결)
- “벡터화 = N차원 숫자 표현” ✅
- “임베딩 = 의미가 비슷하면 가까워지도록 학습된 dense 벡터” ✅
- “유사도 = 코사인(또는 내적/L2)으로 계산” ✅
- “가까운 것 찾기 = 질문 벡터와 DB 벡터들 중 Top‑K 근접 이웃 검색” ✅
- “RAG는 보통 질문이 아니라 문서 chunk를 찾는다(FAQ형은 질문 찾기도 가능)” ✅
참고 문서
- OpenAI Docs — Embeddings guide
- OpenAI Cookbook — Text comparison examples
- Sentence-Transformers Docs — Custom Models / Modules
- Sentence-Transformers Docs — Models (Pooling/Normalize 모듈 참고)
- scikit-learn — cosine_similarity
- Faiss (Meta) — README (Similarity search: L2 / inner product)
- Pinecone Docs — Semantic search guide