프로그래밍/AI·LLM

[AI/LLM] RAG가 뭔데? 임베딩과 벡터DB까지 한 번에 이해하기

이슬먹는 개발자 2026. 7. 3. 14:27
728x90
반응형

ChatGPT한테 "우리 회사 작년 사내 규정 알려줘" 하면 절대 모른다. 학습한 적이 없으니까. 그런데 요즘 "사내 문서 물어보면 답해주는 챗봇"은 어떻게 만드는 걸까? 그 비밀이 바로 RAG다.

오늘은 RAG가 뭔지, 그리고 RAG를 이해하려면 꼭 알아야 하는 임베딩벡터DB까지 한 번에 정리해본다. 이 세 개는 따로 노는 개념이 아니라 하나의 흐름으로 엮여 있어서, 같이 보면 이해가 훨씬 빠르다.


먼저 문제부터: LLM은 모르는 게 많다

GPT 같은 LLM은 똑똑하지만 두 가지 한계가 있다.

  1. 학습 시점 이후의 일을 모른다. 작년 데이터까지만 배웠으면 올해 일은 모른다.
  2. 내 개인/회사 데이터를 모른다. 우리 회사 위키, 내 노션, 사내 규정 같은 건 학습한 적이 없다.

그래서 LLM한테 모르는 걸 물으면 그냥 모른다고 하거나, 더 나쁘게는 그럴듯하게 지어낸다(환각, hallucination).

이걸 해결하는 가장 직관적인 방법은 뭘까? "모르면 자료를 찾아서 보여주고, 그 자료를 보고 답하게 하면 되잖아?" 맞다. 그게 바로 RAG의 핵심 아이디어다.


RAG = 검색해서(Retrieval) + 보강해서(Augmented) + 생성하기(Generation)

RAG는 Retrieval-Augmented Generation의 약자다. 이름을 그대로 풀면 흐름이 보인다.

  1. Retrieval(검색): 사용자가 질문하면, 관련 있는 문서를 먼저 찾아온다.
  2. Augmented(보강): 찾아온 문서를 질문이랑 같이 LLM한테 넘긴다.
  3. Generation(생성): LLM은 그 문서를 참고해서 답을 만든다.

비유하자면 이렇다. 시험을 보는데 LLM 혼자 기억으로 푸는 게 아니라, 오픈북 시험처럼 관련 페이지를 먼저 펼쳐주고 그걸 보고 답하게 하는 거다. 당연히 정확도가 올라가고, 지어내는 것도 줄어든다.

[사용자 질문]
      │
      ▼
[관련 문서 검색]  ← 여기가 핵심! 어떻게 "관련 있는" 문서를 찾지?
      │
      ▼
[질문 + 문서] → [LLM] → [답변]

그런데 여기서 진짜 질문이 생긴다. "관련 있는 문서"를 도대체 어떻게 찾지? 그냥 키워드 검색하면 되는 거 아닌가? 여기서 임베딩이 등장한다.


임베딩(Embedding): 의미를 숫자로 바꾸기

키워드 검색에는 한계가 있다. 사용자가 "퇴사하면 연차 수당 받나요?"라고 물었는데, 문서에는 "근로 종료 시 미사용 휴가 보상"이라고 적혀 있다면? 단어가 하나도 안 겹쳐서 키워드 검색으로는 못 찾는다. 하지만 둘은 같은 의미다.

그래서 필요한 게 임베딩이다. 임베딩은 글자(텍스트)를 의미를 담은 숫자 배열(벡터)로 바꾸는 것이다.

"퇴사하면 연차 수당 받나요?"     → [0.21, -0.88, 0.45, ... ]
"근로 종료 시 미사용 휴가 보상"   → [0.19, -0.85, 0.48, ... ]
"오늘 점심 뭐 먹지"              → [-0.72, 0.33, -0.10, ... ]

핵심은 이거다. 의미가 비슷한 문장은 숫자(벡터)도 비슷하게 나온다. 위에서 첫 번째랑 두 번째는 숫자가 비슷하고, 세 번째(점심)는 완전히 다르다.

이렇게 숫자로 바꿔두면, 두 문장이 얼마나 비슷한지를 수학적으로 계산할 수 있다. 벡터 사이의 거리(또는 각도)를 재면 "이 두 문장이 의미적으로 가깝다/멀다"를 판단할 수 있는 거다. 보통 코사인 유사도(cosine similarity)라는 걸 쓴다.

정리하면, 임베딩 덕분에 "단어가 겹치는 문서"가 아니라 "의미가 비슷한 문서"를 찾을 수 있게 된다.


벡터DB: 임베딩을 저장하고 빠르게 검색하기

이제 문제가 하나 더 생긴다. 회사 문서가 10만 개라고 하자. 사용자가 질문할 때마다 10만 개 벡터랑 일일이 거리를 계산하면 너무 느리다.

그래서 벡터DB(Vector Database)가 필요하다. 벡터DB는 이름 그대로 벡터(임베딩)를 저장하고, 그중에서 가장 비슷한 것들을 빠르게 찾아주는 데 특화된 데이터베이스다.

일반 DB(MySQL 등)는 "id가 3인 행 찾아줘" 같은 정확한 일치 검색에 강하다. 반면 벡터DB는 "이 벡터랑 가장 비슷한 상위 5개 찾아줘" 같은 유사도 검색에 특화돼 있다. 내부적으로는 ANN(근사 최근접 이웃) 같은 알고리즘을 써서, 10만 개를 다 비교하지 않고도 비슷한 걸 빠르게 추려낸다.

대표적인 벡터DB로는 Pinecone, Weaviate, Qdrant, Chroma, 그리고 PostgreSQL 확장인 pgvector 등이 있다. 입문 단계에서는 설치가 간단한 Chroma나, 기존 Postgres에 얹는 pgvector부터 써보는 걸 추천한다.


전체 그림 다시 보기

이제 세 개념이 어떻게 한 흐름으로 엮이는지 다시 보자. RAG는 크게 준비 단계질문 단계로 나뉜다.

준비 단계 (미리 한 번):

회사 문서들 → [임베딩 모델] → 벡터로 변환 → [벡터DB에 저장]

문서를 적당한 크기로 쪼개고(청킹), 각 조각을 임베딩해서 벡터DB에 차곡차곡 넣어둔다.

질문 단계 (사용자가 물을 때마다):

1. 사용자 질문 → [임베딩 모델] → 질문도 벡터로 변환
2. 그 벡터로 [벡터DB] 검색 → 가장 비슷한 문서 조각 N개 가져옴
3. [질문 + 가져온 문서] → [LLM] → 최종 답변

질문도 똑같이 벡터로 바꾼 다음, 벡터DB에서 의미가 가까운 문서를 찾고, 그걸 LLM한테 같이 넘겨서 답하게 하는 거다.


아주 간단한 의사코드로 보기

말로만 보면 추상적이니까, 파이썬 의사코드로 흐름만 잡아보자.

# === 준비 단계 ===
docs = load_company_documents()        # 회사 문서 불러오기
chunks = split_into_chunks(docs)       # 적당히 쪼개기

for chunk in chunks:
    vector = embedding_model.embed(chunk)   # 임베딩
    vector_db.save(vector, text=chunk)      # 벡터DB에 저장


# === 질문 단계 ===
question = "퇴사하면 연차 수당 받나요?"

q_vector = embedding_model.embed(question)          # 질문 임베딩
related = vector_db.search(q_vector, top_k=3)       # 비슷한 문서 3개 검색

prompt = f"""
아래 문서를 참고해서 질문에 답해줘.

문서:
{related}

질문: {question}
"""

answer = llm.generate(prompt)    # LLM이 문서 보고 답변
print(answer)

핵심은 vector_db.search()관련 문서를 먼저 찾고, 그걸 프롬프트에 넣어서 LLM이 그 문서를 근거로 답하게 한다는 점이다. 이게 RAG의 전부다.


정리

개념 한 줄 요약 역할
RAG 검색해서 찾은 문서를 보고 답하기 전체 흐름
임베딩 텍스트를 의미가 담긴 벡터로 변환 의미 비교 가능하게
벡터DB 벡터를 저장하고 비슷한 것 빠르게 검색 빠른 유사도 검색

세 줄로 압축하면 이렇다.

  • LLM은 내 데이터를 모르니까, 관련 문서를 찾아서 같이 넘겨주자 → 이게 RAG
  • "관련 문서"를 의미 기준으로 찾으려면 텍스트를 숫자로 바꿔야 한다 → 이게 임베딩
  • 그 숫자(벡터)를 빠르게 검색하려면 전용 DB가 필요하다 → 이게 벡터DB

RAG는 지금 LLM 애플리케이션에서 가장 많이 쓰이는 패턴 중 하나다. 챗봇, 사내 문서 검색, 고객 지원 자동화 같은 게 거의 다 이 구조로 돌아간다. 오늘은 큰 그림만 잡았으니, 다음엔 직접 Chroma나 pgvector로 간단한 RAG를 만들어보는 실습 글로 이어가보자.

728x90
반응형