LLM

대 LLM의 시대, 더 좋은 답변을 위한 방법 RAG(검색 증강 생성) 알아보기 + 벡터 DB

Luti 2025. 4. 17. 22:58

 

 

 

작년 처음 프로그래밍 공부를 시작하고 4개월 차쯤에 1~2주 정도 기간 동안 간단하게 저의 도서 쇼핑몰 사이트에 챗봇을 붙여 넣는 토이 프로젝트를 진행하게 되었습니다.

정말 병아리 시절이라 (사실 지금도 ...) 차마 저 허접한 코드를 다시 돌려보는 게 스스로 부끄럽고 굉장히 오글거리는데요...

이때가 제가 LLM을 활용한 프로그래밍에 관심을 갖기 시작했던 시기였습니다.

조잡하긴 하지만 같은 기관에서 공부하던 동료 개발자 한 분으로부터 제가 SQL을 미리 정의해놓고 적절한 테이블을 조회하는 함수를 프롬프트에 달아놓는 방식이 마치 RAG와 같다고 했습니다.

그때 RAG라는 단어를 처음 접하기도 했습니다.

 

어찌 되었든, 그로부터 몇 달이 지난 후 이제서야 RAG에 대해 자세히 알아보고 공부하게 되었는데요, 이번 포스트에서는 RAG라는 용어를 이제 막 처음 접하신 분들께 개략적인 개요를 설명해 드리는 글을 작성해보고자 합니다.

 

 

 

 

# 00. LLM의 문제점

RAG가 등장한 이유는 기존 LLM의 문제점을 극복하기 위함입니다.

gpt와 같은 챗봇 서비스를 이용하신지 얼마 안 된 분들께서는 gpt가 마치 전지전능해 보이고, 어떠한 대답도 할 수 있을 것으로 보일 수 있습니다.

하지만 2년 넘게 유료 구독을 해왔던 저의 입장에서는 gpt와 같은 기존 LLM의 한계가 순간순간 느껴질 때가 있었습니다.

 

아래는 대표적으로 거론되는 LLM의 문제점들입니다.

 

1. Outdated knowledge

LLM은 오직 학습된 데이터에만 의존해 답변을 생성합니다.
시간이 지남에 따라 새로운 사실·정보가 지속적으로 추가되기 때문에, 학습 시점 이후의 실시간성을 반영할 수 없고 점차 정확도가 떨어집니다.

 

2. Bias and fairness

LLM은 학습된 데이터셋에 내재된 편향(bias)을 그대로 상속받습니다.
종교적·정치적·문화적 관점 등 다양한 편향이 모델 출력에 영향을 미쳐, 민감한 주제에서 공정하지 않은 결과를 도출할 위험이 있습니다.

 

3. Cost

LLM을 학습하는데에는 막대한 자원이 필요합니다.

수천 대의 GPU 클러스터 운영과 대규모 데이터 전처리 비용으로 인해 새로운 데이터를 매번 추가적으로 학습시키기에는 제한적입니다.

 

4. Limited domain expertise

LLM은 일반적인 대규모 웹·문서 데이터를 기반으로 학습되므로 특정 산업 또는 분야에 특화된 지식을 충분히 내재화하기 어렵습니다.
의료, 법률, 금융과 같은 전문 영역에서는 정확하고 깊이 있는 답변을 제공하는 데 한계가 있습니다.

 

# 01. About RAG

RAG?

RAG는 Retrieval Augmented Generation의 약자로 한국어로 직역하면 검색 증강 생성입니다.

세 단어중 가장 핵심이 되는 단어는 Retrieval(검색)입니다.

RAG는 답변에 필요한 외부 세계의 데이터를 DB로부터 '검색'합니다.

검색으로 찾은 문서들을 토대로 기존의 답변을 증강해서 생성합니다.

 

필요한 문서를 검색(Retrieval)을 통해 찾아내고 가져온 문서를 프롬프트에 보강(혹은 증강/Augmented)시켜 답변을 생성(Generation) 하는 일련의 과정 및 방식을 RAG라고 이해해 주시면 되겠습니다.

 

RAG가 왜 필요할까?

RAG가 필요한 이유를 조금 더 직관적으로 이해해보기 위해 한 가지 상황을 예로 들겠습니다.

사용자의 일반적인 질문에 대해서는 그림과 같이 LLM은 학습된 데이터셋을 기반으로 답변을 출력합니다.

하지만, 특수하고 지엽적인 정보에 대한 답변을 요구하는 사용자의 질문에 대해서는 LLM이 퀄리티가 좋은 답변을 출력하지 못하거나, 모르는 정보를 아는 척 허풍을 떠는 할루시네이션(Hallucination) 현상이 발생할 수 있습니다.

위에서 말씀드렸듯 비용 문제가 있기 때문에 모든 특수하고 전문적인 도메인 데이터에 대해 LLM을 학습시킬 수는 없습니다.

때문에 RAG에서는 특정 도메인 데이터를 미리 준비해놓고, 사용자 질문에 대해 관련도가 높은 문서들만 추출하여 LLM이 답변에 참고할 수 있도록 프롬프트로 넣어줍니다.

이렇게 함으로써 LLM은 기존에 학습된 데이터에만 의존한다는 단점을 극복하고, 외부 세계의 데이터가 준비만 되어있다면 어떠한 질문에 대해서도 적절하게 답변을 출력할 수 있습니다.

 

입력부터 답변까지

지금부터는 RAG 파이프라인 내에서 사용자의 질문부터 LLM이 답변하기까지의 과정을 조금 더 자세하게 알아보겠습니다.

 

1. Pre‑processing

 

1. Document load

외부 세계의 데이터를 준비합니다.

데이터는 PDF, CSV, 웹 페이지 등 다양한 형태(비정형)로 있을 수 있습니다.

 

2. Text split

긴 문서를 의미 있는 chunk 단위로 분리합니다.

문서가 너무 짧으면 LLM이 참고할 정보의 양이 적어져서 답변의 질이 안 좋아집니다.

반면, 문서가 너무 길면 막대한 정보 안에서 필요한 정보를 찾기 힘들어하는 Needle In A Haystack 문제가 발생할 수 있습니다.

때문에 적절한 사이즈의 chunk로 문서를 분리해야 하며, 문서를 분리하는 데에는 글자 수로 분할, 재귀적으로 텍스트 분할, 문맥을 고려한 분할 등 여러 가지 방법이 있으며, 자세한 내용은 이후 기회가 되면 따로 글을 준비해 보겠습니다.

 

3. Embedding

데이터를 벡터 형태로 변환하는 과정을 임베딩이라고 합니다.
청크 단위로 분리된 각 문서를 벡터 형태로 임베딩합니다.

RAG에서는 데이터를 텍스트 혹은 이미지 그대로 DB에 저장하는 것이 아니라, 임베딩을 통해 벡터 형태로 저장합니다.

임베딩 방식은 임베딩 모델마다 다르며, 임베딩 모델에는 Word2Vec, BERT 혹은 OpenAI에서 제공하는 임베딩 API 등 다양하게 존재합니다.

 

4. Store to Vector DB
RAG에서는 데이터를 일반적인 RDB나 NoSQL DB가 아닌 벡터 DB에 저장합니다.

벡터 DB는 Chroma DB, FAISS, Milvus, Qdrant, Weaviate 등 용도와 목적에 따라 다양한 종류가 있습니다.

 

 

2. Query-time Processing

사용자의 질의 역시 마찬가지로 임베딩 모델을 통해 벡터화를 진행합니다.

이후 벡터화된 사용자 쿼리와 DB에 저장된 데이터들을 유사도 기반 검색을 통해 상위 K개의 청크를 추출합니다.

유사도를 구하는 방식에는 코사인 유사도, 유클리드 거리 등 다양한 방식이 존재합니다.

추출된 문서들을 LLM에 프롬프트로 넣어주고 LLM은 답변을 생성합니다.

 

# 02. 벡터 DB

RAG에서는 외부 데이터를 RDB가 아닌 벡터 DB에 저장합니다.

그 이유가 뭘까요?

 

RDB vs 벡터 DB

벡터 DB를 사용하는 이유를 알아보기 위해 먼저 RDB와 벡터 DB의 차이점을 살펴보겠습니다.

 

1. 데이터 모델 & 저장 방식

  • RDB: 정형화된 스키마에 따라 테이블을 구성하고, 각 행(row)에 값을 저장
  • 벡터 DB: 텍스트·이미지 등 비정형 데이터를 임베딩하여 고차원 벡터로 변환 후 저장

2. 인덱싱 & 검색

  • RDB: B‑Tree, Hash Index 등을 사용해 정확 매칭(point lookup)과 범위 검색 지원
  • 벡터 DB: HNSW, IVF‑PQ, Annoy 등의 근사 최근접 이웃(ANN) 알고리즘을 사용해 유사도 기반 검색

3. 쿼리 방식

  • RDB: SQL 쿼리를 통해 JOIN, GROUP BY, 집계함수 등을 수행
  • 벡터 DB: “주어진 쿼리 벡터와 가장 유사한 K개의 벡터”를 찾는 k‑NN 검색이 핵심

4. 일관성 및 트랜잭션

  • RDB: 강력한 ACID 트랜잭션 지원 → 복잡한 비즈니스 로직 구현에 적합
  • 벡터 DB: 트랜잭션 기능은 제한적

5. 확장성 & 성능

  • RDB: 단일 노드에서 수직 확장(메모리·CPU 증설)
  • 벡터 DB: 분산 클러스터로 수평 확장, 대용량 벡터 저장·검색에 최적화

 

벡터 DB여야 하는 이유?

RDB의 목적은 정형화된 데이터를 SQL문을 통해 정확하게 가져오는 것입니다.

반면, 벡터 DB의 목적은 비정형 데이터에 대해 유사한 데이터를 읽어오는 것입니다.

 

두 DB의 가장 포인트가 되는 차이점은 정확성 vs 유사성이라고 생각합니다.

주문 및 결제 혹은 사용자 정보 등을 다루는 상황과 같이 데이터의 무결성이 중요한 경우 RDB를 사용해 데이터를 다룹니다.

하지만, RAG 시스템에서 사용자 질문에 대해서 답변에 참고할 데이터가 무엇인지 정확하게 알고 읽어오는 것은 불가능합니다。

때문에 사용자 질문과 데이터들 간의 고차원 유사도 검색을 통해 유사한 데이터를 읽어오기 위해 벡터 DB를 사용하는 것이고、

유사도 검색을 위해 데이터와 사용자의 질문을 임베딩하는 과정이 필요하다고 이해해 주시면 되겠습니다。


 

AI의 발전이 가속화됨에 따라 개발자의 역할을 AI가 대신할 수 있는 부분이 점점 많아지고 있습니다。

시대의 흐름에 뒤처지지 않기 위해 부단히 노력해야겠습니다…