TIL/[TIL]

[TIL]Embedding과 VectorStore

namerong 2026. 7. 23. 23:30

1. 학습 주제

RAG에서 외부 문서를 검색하기 위해 필요한 Embedding과 VectorStore 흐름을 학습했다.
텍스트를 그대로 비교하는 것이 아니라, 문장의 의미를 숫자 벡터로 변환한 뒤 질문과 가까운 문서를 찾는 방식이다.

핵심 내용은 다음과 같다.

  • 텍스트를 Embedding Vector로 변환하기
  • Cosine Similarity로 의미적 유사도 비교하기
  • VectorStore가 필요한 이유 이해하기
  • LangChain Document 구조 이해하기
  • metadata를 활용한 검색 필터링
  • top_k로 상위 검색 결과 가져오기
  • VectorStore에 문서 추가, 검색, 삭제하기

2. Embedding이란?

Embedding은 텍스트를 숫자 벡터로 바꾸는 과정이다.

사람은 아래 두 문장이 비슷한 의미라는 것을 바로 알 수 있다.

수강 신청을 취소하면 결제 금액을 환불받을 수 있습니다.
강의를 철회하면 지불한 돈을 돌려드립니다.

하지만 컴퓨터는 문장을 그대로 이해하지 못한다.
그래서 문장을 숫자 목록인 Vector로 바꾼 뒤, 벡터끼리 얼마나 가까운지 비교한다.

document_vectors = embeddings.embed_documents(DOCUMENTS)
question_vector = embeddings.embed_query(QUESTION)

여기서 중요한 점은 문서와 질문을 같은 Embedding 모델로 변환해야 한다는 것이다.
그래야 질문 벡터와 문서 벡터를 같은 기준에서 비교할 수 있다.


3. Cosine Similarity

Cosine Similarity는 두 벡터의 방향이 얼마나 비슷한지 계산하는 방식이다.

값이 높을수록 의미가 비슷하다고 볼 수 있다.

def cosine_similarity(vector_a, vector_b):
    dot = sum(a * b for a, b in zip(vector_a, vector_b))
    norm_a = math.sqrt(sum(value * value for value in vector_a))
    norm_b = math.sqrt(sum(value * value for value in vector_b))
    return dot / (norm_a * norm_b)

예를 들어 질문이 다음과 같다면:

수업을 취소하면 돈을 돌려받을 수 있나요?

환불 관련 문장이 점심 메뉴 문장보다 더 높은 similarity를 가진다.
즉, 단어가 완전히 같지 않아도 의미가 비슷하면 검색될 수 있다.


4. VectorStore가 필요한 이유

Embedding Vector만 있어도 직접 검색은 가능하다.
하지만 직접 구현하면 개발자가 모든 과정을 관리해야 한다.

1. 문서를 Embedding으로 변환
2. 질문을 Embedding으로 변환
3. 질문 Vector와 모든 문서 Vector 비교
4. 유사도 점수 계산
5. 점수 기준 정렬
6. 상위 결과 선택
7. 원문 Document와 Vector가 어긋나지 않도록 관리

이 과정을 직접 처리하면 코드가 복잡해지고 실수하기 쉽다.
VectorStore는 이 흐름을 묶어서 처리해주는 저장소이다.

store = InMemoryVectorStore(create_embeddings())
store.add_documents(DOCUMENTS, ids=[str(document.id) for document in DOCUMENTS])
results = store.similarity_search_with_score(question, k=2)

즉, VectorStore는 단순 배열 저장소가 아니라 다음을 함께 관리한다.

  • 원문 텍스트
  • Embedding Vector
  • 문서 ID
  • metadata
  • 유사도 검색
  • 상위 결과 반환

5. Document와 Metadata

LangChain에서는 검색할 문서를 Document 객체로 다룬다.

Document(
    id="class-line-001",
    page_content="RAG는 Retrieval Augmented Generation의 약자이다.",
    metadata={
        "source": "chatbot_knowledge_base.txt",
        "line": 1,
        "topic": "retrieval",
    },
)

각 필드의 역할은 다음과 같다.

필드 의미
id 문서를 구분하는 고유값
page_content 실제 검색 대상이 되는 본문
metadata 출처, 줄 번호, 주제 같은 부가 정보

metadata는 답변의 근거를 표시하거나 특정 주제만 검색할 때 사용된다.

예를 들어 topic이 memory인 문서만 검색하고 싶다면 filter를 사용할 수 있다.

filter=lambda document: document.metadata.get("topic") == "memory"

6. top_k 검색

top_k는 검색 결과 중 상위 몇 개를 가져올지 정하는 값이다.

results = store.similarity_search_with_score(
    question,
    k=3
)

k=3이면 질문과 가장 비슷한 문서 3개를 반환한다.

검색 결과에는 보통 다음 정보가 함께 나온다.

similarity score
document id
topic
source
page_content

RAG에서는 이 검색 결과를 그대로 사용자에게 보여주기보다는, LLM에게 context로 전달해서 답변의 근거로 사용한다.


7. VectorStore 작업 흐름

이번 실습에서 확인한 VectorStore 흐름은 다음과 같다.

텍스트 파일 읽기
-> 한 줄씩 Document로 변환
-> Document에 metadata 추가
-> Embedding 모델 생성
-> VectorStore 생성
-> add_documents로 문서 저장
-> 질문 입력
-> similarity_search_with_score로 검색
-> source, score, content 출력

문서 저장은 다음처럼 처리한다.

store, stored_ids = build_inmemory_store(documents)

검색은 다음처럼 처리한다.

results = store.similarity_search_with_score(
    question,
    k=top_k,
    filter=make_filter(topic)
)

삭제도 가능하다.

store.delete(ids=[deleted_id])

삭제 후 같은 질문으로 다시 검색하면 해당 문서는 결과에서 제외된다.


8. RAG와 VectorStore의 관계

RAG 흐름에서 VectorStore는 “관련 문서를 찾는 역할”을 맡는다.

사용자 질문
-> 질문을 Embedding Vector로 변환
-> VectorStore에서 비슷한 문서 검색
-> 검색된 문서를 Context로 구성
-> LLM에게 질문 + Context 전달
-> 문서 기반 답변 생성

일반 LLM은 모델이 이미 알고 있는 지식으로 답변하지만, RAG는 외부 문서를 먼저 검색한 뒤 그 내용을 근거로 답변한다.

그래서 VectorStore는 RAG에서 매우 중요한 중간 저장소이다.


9. 핵심 정리

  1. Embedding은 텍스트를 숫자 벡터로 바꾸는 과정이다.
  2. 비슷한 의미의 문장은 비슷한 방향의 벡터를 가진다.
  3. Cosine Similarity는 두 벡터의 의미적 유사도를 계산할 때 사용한다.
  4. VectorStore는 Embedding Vector와 원문 Document를 함께 저장하고 검색한다.
  5. LangChain Document는 page_content와 metadata를 함께 가진다.
  6. metadata는 출처 표시와 검색 필터링에 사용할 수 있다.
  7. top_k는 검색 결과를 몇 개 가져올지 정하는 값이다.
  8. RAG에서는 VectorStore 검색 결과가 LLM 답변의 근거 Context가 된다.
  9. VectorStore를 사용하면 직접 벡터 비교, 정렬, 원문 연결을 관리하지 않아도 된다.
  10. 검색 품질을 확인할 때는 질문, 검색 결과, source, similarity score를 함께 보는 것이 중요하다.