임베딩은 RAG를 공부할 때 꼭 이해해야 하는 핵심 개념입니다.
RAG는 사용자의 질문과 관련된 문서를 찾아 LLM에게 전달하는 구조입니다. 그런데 컴퓨터가 문장의 의미를 사람처럼 바로 이해하는 것은 아닙니다.
그래서 문장이나 문서 조각을 컴퓨터가 비교할 수 있는 숫자 형태로 바꿔야 합니다. 이때 사용하는 과정이 바로 Embedding입니다.
임베딩이란?
임베딩은 텍스트를 의미 기반의 숫자 표현으로 바꾸는 작업입니다.
예를 들어 다음과 같은 문장이 있다고 해보겠습니다.
연차 신청은 어디서 하나요?
임베딩 모델은 이 문장을 다음과 같은 숫자 배열로 변환합니다.
[0.91, 0.82, 0.13, -0.44, ...]
이 숫자 배열을 Vector라고 부릅니다.
정리하면 다음과 같습니다.
Embedding = 텍스트를 숫자 Vector로 바꾸는 작업 또는 모델
Vector = Embedding 결과로 나온 숫자 배열
즉, 임베딩은 문장을 숫자로 바꾸는 과정이고, 벡터는 그 결과값입니다.

왜 문장을 숫자로 바꿔야 할까?
사람은 문장을 보면 의미를 이해할 수 있습니다.
예를 들어 아래 문장들은 단어가 조금씩 다르지만, 사람이 보기에는 비슷한 의미라는 것을 알 수 있습니다.
연차 신청은 어디서 하나요?
휴가 신청 방법 알려줘
휴가신청 메뉴가 어디야?
세 문장은 표현은 다르지만 결국 비슷한 내용을 묻고 있습니다.
휴가나 연차를 어디에서 신청하는가?
하지만 컴퓨터는 기본적으로 문장의 의미를 사람처럼 바로 이해하지 못합니다. 그래서 문장을 계산 가능한 형태로 바꿔야 합니다.
이때 문장을 숫자 배열, 즉 Vector로 바꾸면 컴퓨터가 문장끼리 얼마나 비슷한지 계산할 수 있습니다.
임베딩 숫자는 가나다순으로 정해지는 것이 아니다
임베딩을 처음 접하면 숫자가 어떤 기준으로 정해지는지 헷갈릴 수 있습니다.
임베딩 숫자는 가나다순, 알파벳순, 단어 번호처럼 정해지는 것이 아닙니다.
예를 들어 이런 방식이 아닙니다.
가 = 1
나 = 2
다 = 3
연차 = 100
휴가 = 200
신청 = 300
이런 것은 단순 번호 매기기에 가깝습니다.
임베딩은 단어의 순서 번호가 아니라, 문장의 의미와 문맥 관계를 반영해 숫자를 만듭니다.
예를 들어 다음 표현들은 비슷한 상황에서 자주 사용됩니다.
연차 신청
휴가 신청
휴가신청 메뉴
근태관리
임베딩 모델은 많은 텍스트를 학습하면서 이런 표현들이 의미적으로 가깝다는 것을 파악합니다.
그래서 의미가 비슷한 문장들은 비슷한 숫자 배열로 표현될 수 있습니다.
연차 신청은 어디서 하나요?
→ [0.91, 0.82, 0.13]
휴가 신청 방법 알려줘
→ [0.89, 0.80, 0.15]
휴가신청 메뉴가 어디야?
→ [0.90, 0.81, 0.12]
반대로 전혀 다른 주제의 문장은 다른 숫자 배열로 표현될 가능성이 높습니다.
서버 로그 확인 방법 알려줘
→ [-0.22, 0.44, 0.78]
물론 위 숫자는 이해를 돕기 위한 예시입니다. 실제 임베딩 벡터는 훨씬 길고, 사람이 각 숫자의 의미를 직접 해석하기는 어렵습니다.
벡터 공간에서 가깝다는 말의 의미
임베딩을 설명할 때 자주 나오는 표현이 있습니다.
의미가 비슷한 문장들은 벡터 공간에서 가까운 위치에 놓입니다.
이 말은 어렵게 들리지만, 쉽게 말하면 다음과 같습니다.
의미가 비슷한 문장끼리는 숫자 배열도 비슷하게 나옵니다.
예를 들어 2차원 좌표로 단순화해서 생각해보겠습니다.
A: 연차 신청은 어디서 하나요? → [1.0, 1.0]
B: 휴가 신청 방법 알려줘 → [1.1, 0.9]
C: 서버 로그 확인 방법 → [8.0, 7.5]
A와 B는 좌표가 비슷합니다. 둘 다 휴가나 연차 신청과 관련된 문장이기 때문입니다.
반면 C는 서버 로그에 대한 문장이므로 A, B와 의미가 다릅니다. 그래서 좌표도 멀리 떨어져 있다고 볼 수 있습니다.
RAG는 이 원리를 이용합니다.
사용자 질문 Vector와 가까운 문서 Chunk Vector를 찾는다.
즉, 질문과 의미가 비슷한 문서 조각을 찾는 것입니다.
키워드 검색과 임베딩 검색의 차이
임베딩 검색은 기존 키워드 검색과 차이가 있습니다.
키워드 검색
키워드 검색은 단어가 정확히 포함되어 있는지를 중심으로 찾습니다.
예를 들어 문서에 다음과 같은 내용이 있다고 해보겠습니다.
연차 신청은 HR 시스템 > 근태관리 > 휴가신청 메뉴에서 진행한다.
사용자가 다음과 같이 검색하면 쉽게 찾을 수 있습니다.
연차 신청
문서에 “연차”와 “신청”이라는 단어가 포함되어 있기 때문입니다.
하지만 사용자가 이렇게 질문하면 어떨까요?
휴가는 어디서 등록해?
문서에 “휴가”나 “등록”이라는 단어가 정확히 없으면 키워드 검색은 이 문서를 놓칠 수 있습니다.
임베딩 검색
임베딩 검색은 단어가 정확히 일치하는지만 보지 않습니다.
문장의 의미가 비슷한지를 비교합니다.
문서:
연차 신청은 HR 시스템 > 근태관리 > 휴가신청 메뉴에서 진행한다.
질문:
휴가는 어디서 등록해?
두 문장은 단어가 완전히 같지는 않습니다. 하지만 의미는 비슷합니다.
- 연차 ≈ 휴가
- 신청 ≈ 등록
- 어디서 ≈ 메뉴, 경로
그래서 임베딩 검색은 키워드가 정확히 일치하지 않아도 관련 문서를 찾을 수 있습니다.
| 구분 | 검색 기준 | 예시 |
|---|---|---|
| 키워드 검색 | 단어 일치 여부 | “연차 신청”이라는 단어가 있는 문서 검색 |
| 임베딩 검색 | 의미 유사도 | “휴가 등록”처럼 표현이 달라도 의미가 비슷한 문서 검색 |
다만 임베딩 검색이 항상 키워드 검색보다 좋은 것은 아닙니다. 정확한 상품명, 법령명, 코드명, 고유명사처럼 단어 자체가 중요한 경우에는 키워드 검색이 더 정확할 수 있습니다.
그래서 실제 RAG에서는 키워드 검색과 임베딩 검색을 함께 사용하는 하이브리드 검색을 활용하기도 합니다. 키워드 일치와 의미 유사도를 함께 고려하면 검색 정확도를 더 높일 수 있습니다.
문서도 임베딩하고 질문도 임베딩한다
RAG에서는 문서만 임베딩하는 것이 아닙니다. 사용자 질문도 임베딩합니다.
왜냐하면 Vector DB는 질문 Vector와 문서 Chunk Vector를 비교해서 관련 문서를 찾기 때문입니다.
1. 문서 저장 시점
먼저 문서를 Chunk로 나누고, 각 Chunk를 임베딩합니다.
문서 Chunk:
연차 신청은 HR 시스템 > 근태관리 > 휴가신청 메뉴에서 진행한다.
Embedding 결과:
[0.15, -0.21, 0.03, 0.88, ...]
이 Vector를 Vector DB에 저장합니다.
2. 질문 시점
사용자가 질문합니다.
연차는 어디서 신청해?
이 질문도 임베딩 모델을 통해 Vector로 변환합니다.
질문 Vector:
[0.14, -0.19, 0.05, 0.82, ...]
그다음 Vector DB에서 질문 Vector와 가까운 문서 Chunk Vector를 찾습니다.
질문 Vector
↔
문서 Chunk Vector
이렇게 문서와 질문이 같은 Vector 형식으로 변환되어야 서로 비교할 수 있습니다.
보통 문서와 질문은 같은 임베딩 모델로 변환합니다. 서로 다른 임베딩 모델을 사용하면 Vector 공간이 달라져 비교가 자연스럽지 않을 수 있습니다.
임베딩 모델과 LLM은 역할이 다르다
RAG를 공부하다 보면 LLM이 모든 것을 처리한다고 생각하기 쉽습니다.
하지만 RAG 구조에서는 역할이 나뉩니다.
| 구성요소 | 역할 |
|---|---|
| 임베딩 모델 | 문서와 질문을 Vector로 변환 |
| Vector DB | Vector 저장 및 유사도 검색 |
| Retriever | 질문과 관련된 문서 Chunk 검색 |
| LLM | 검색된 Context를 바탕으로 최종 답변 생성 |
즉, LLM이 Vector DB에 직접 저장하는 것이 아닙니다.
문서를 읽고, Chunk로 나누고, 임베딩 모델을 호출하고, Vector DB에 저장하는 것은 별도의 애플리케이션 로직이 담당합니다.
문서 Chunk
→ 임베딩 모델
→ Vector 생성
→ 애플리케이션 로직이 Vector DB에 저장
LLM은 주로 마지막 단계에서 검색된 내용을 읽고 답변을 생성하는 역할을 합니다.
유사도 검색이란?
Vector DB는 질문 Vector와 문서 Vector가 얼마나 비슷한지 계산합니다.
이 과정을 보통 유사도 검색이라고 합니다.
대표적으로 다음과 같은 개념이 사용됩니다.
- Cosine Similarity
- Euclidean Distance
- Dot Product
처음부터 수식까지 깊게 알 필요는 없습니다. 지금은 다음 정도로 이해하면 충분합니다.
유사도 검색은 질문 Vector와 가까운 문서 Vector를 찾는 과정입니다.
예를 들어 사용자가 이렇게 질문했다고 해보겠습니다.
휴가 신청 메뉴 알려줘
Vector DB는 이 질문과 의미적으로 가까운 Chunk를 찾습니다.
검색 결과:
1위: 연차 신청은 HR 시스템 > 근태관리 > 휴가신청 메뉴에서 진행한다.
2위: 반차 신청도 휴가신청 메뉴에서 가능하다.
3위: 휴가 신청은 팀장 승인 후 완료된다.
이 검색 결과가 LLM에게 Context로 전달되고, LLM은 이를 참고해 답변을 생성합니다.
Vector 차원이란?
임베딩 결과로 나오는 Vector는 보통 숫자가 매우 많습니다.
[0.15, -0.21, 0.03, 0.88, ...]
여기서 숫자가 3개라면 3차원 Vector라고 볼 수 있습니다.
실제 임베딩 모델은 수백 차원 또는 수천 차원의 Vector를 만들 수 있습니다.
384차원
768차원
1536차원
3072차원
하지만 각 차원을 사람이 직접 해석하는 것은 어렵습니다.
예를 들어 다음처럼 이해하면 안 됩니다.
1번째 차원 = 연차 관련도
2번째 차원 = 신청 관련도
3번째 차원 = 회사 관련도
각 차원은 임베딩 모델이 학습한 복잡한 의미 표현입니다.
개발자 관점에서는 다음과 같이 이해하면 됩니다.
임베딩 Vector는 텍스트의 의미를 표현하는 고차원 숫자 좌표입니다.
RAG에서 임베딩 품질이 중요한 이유
RAG에서 임베딩은 검색 품질과 직접 연결됩니다.
RAG 흐름을 다시 보면 다음과 같습니다.
문서 Chunk
→ Embedding
→ Vector DB 저장
사용자 질문
→ Embedding
→ 비슷한 Chunk 검색
→ LLM 답변
만약 임베딩 품질이 낮으면 어떻게 될까요?
질문과 관련 없는 Chunk가 검색됨
→ 잘못된 Context가 LLM에게 전달됨
→ 답변 품질이 떨어짐
즉, LLM이 아무리 좋아도 앞에서 가져온 Context가 엉뚱하면 답변도 부정확해질 수 있습니다.
그래서 RAG의 품질은 단순히 LLM 성능만으로 결정되지 않습니다.
- 문서를 어떻게 Chunk로 나눴는지
- 어떤 임베딩 모델을 사용했는지
- Retriever가 관련 문서를 잘 찾는지
- 검색된 Context를 Prompt에 어떻게 넣는지
이런 요소들이 함께 영향을 줍니다.
예시: 블로그 작성 가이드 RAG
블로그 작성 가이드를 RAG에 넣는다고 가정해보겠습니다.
문서 Chunk에 다음 내용이 있습니다.
청년정책 글은 신청 대상, 신청 기간, 지원 내용, 신청 방법, 유의사항 순서로 작성한다.
이 Chunk를 임베딩해서 Vector DB에 저장합니다.
이후 사용자가 이렇게 질문합니다.
청년미래적금 글은 어떤 순서로 쓰면 돼?
질문도 임베딩됩니다.
임베딩 검색은 다음 두 표현이 의미적으로 관련 있다고 판단할 수 있습니다.
청년정책 글 작성 순서
청년미래적금 글 구성
그래서 관련 Chunk를 찾아오고, LLM은 이를 참고해 다음과 같이 답변할 수 있습니다.
청년미래적금 글은 신청 대상, 신청 기간, 혜택, 신청 방법, 유의사항 순서로 구성하면 좋습니다.
이처럼 임베딩은 단어가 완전히 같지 않아도 의미가 비슷한 문서를 찾는 데 도움을 줍니다.
임베딩에서 자주 하는 오해
1. 임베딩 숫자는 사람이 직접 정한다?
아닙니다. 임베딩 숫자는 사람이 직접 정하는 것이 아니라, 임베딩 모델이 텍스트의 의미와 문맥 관계를 바탕으로 생성합니다.
2. 임베딩은 가나다순이나 단어 번호다?
아닙니다. 임베딩은 단순 번호표가 아니라 의미 기반 숫자 표현입니다.
3. Vector DB가 임베딩을 만든다?
일반적으로 아닙니다. 임베딩 모델이 Vector를 만들고, Vector DB는 그 Vector를 저장하고 검색합니다.
4. 단어가 같아야 검색된다?
아닙니다. 임베딩 검색은 단어가 달라도 의미가 비슷하면 관련 문서를 찾을 수 있습니다.
5. 임베딩만 좋으면 RAG가 완벽해진다?
아닙니다. 임베딩은 중요하지만 Chunking, Retriever 설정, Prompt 구성, LLM 품질도 함께 중요합니다.
개발자 관점에서 보는 임베딩 흐름
개발자 관점에서는 임베딩을 저장 로직과 질문 로직으로 나누어 이해하면 쉽습니다.
저장 로직
1. 문서를 읽는다.
2. 문서를 Chunk로 나눈다.
3. 각 Chunk를 임베딩 모델에 보낸다.
4. Vector를 받는다.
5. Chunk 내용, Vector, metadata를 Vector DB에 저장한다.
질문 로직
1. 사용자 질문을 받는다.
2. 질문을 임베딩 모델에 보낸다.
3. 질문 Vector를 받는다.
4. Vector DB에서 비슷한 Chunk Vector를 찾는다.
5. 검색된 Chunk를 Context로 만든다.
6. Context와 질문을 Prompt에 넣는다.
7. LLM이 답변한다.
이 흐름을 이해하면 RAG에서 임베딩이 왜 필요한지 더 명확해집니다.
정리
이번 글에서는 RAG의 핵심 개념 중 하나인 임베딩을 살펴봤습니다.
- 임베딩은 텍스트를 의미 기반 숫자 Vector로 바꾸는 작업입니다.
- Vector는 임베딩 결과로 나온 숫자 배열입니다.
- 임베딩 숫자는 가나다순이나 단어 번호가 아니라 의미와 문맥 관계를 바탕으로 만들어집니다.
- RAG에서는 문서 Chunk와 사용자 질문을 모두 임베딩합니다.
- 문서와 질문이 같은 Vector 형식이어야 서로 유사도를 비교할 수 있습니다.
- 임베딩 검색은 키워드가 정확히 일치하지 않아도 의미가 비슷한 문서를 찾을 수 있습니다.
- 다만 고유명사나 정확한 용어가 중요한 경우에는 키워드 검색과 함께 사용하는 하이브리드 검색이 도움이 될 수 있습니다.
- 임베딩 품질이 낮으면 엉뚱한 Context가 LLM에게 전달되어 답변 품질이 떨어질 수 있습니다.
한 문장으로 정리하면 다음과 같습니다.
임베딩은 문서와 질문을 같은 의미 좌표계의 Vector로 바꿔, 서로 의미가 비슷한지 비교할 수 있게 해주는 과정입니다.
다음 글에서는 임베딩된 Vector를 저장하고 검색하는 Vector DB와, 질문에 맞는 문서를 찾아오는 Retriever를 더 자세히 살펴보겠습니다.