내일배움캠프

[내일배움캠프] RAG

munsik22 2026. 6. 10. 19:46

🧩 임베딩과 벡터 저장소

임베딩(Embedding)

임베딩은 텍스트, 이미지, 오디오와 같은 비정형 데이터를 컴퓨터가 이해할 수 있는 부동 소수점 숫자의 배열(벡터)로 변환하는 과정을 의미한다.

 

굳이 벡터로 변환하는 이유는, 데이터를 다차원 공간상의 한 점으로 표현하면 수학적인 거리 계산을 통해 데이터 간의 의미적 유사성을 파악할 수 있기 때문이다.

  • 과거: 검색은 글자 단위 매칭이므로 "강아지"를 입력해도 "시츄"라는 단어는 나오지 않는다.
  • 현재: "강아지"가 [0.82, -0.31, 0.47, 0.15, ...], "시츄"가 [0.79, -0.28, 0.52, 0.18, ...] 라는 숫자의 묶음을 가진다고 가정해 보자.
    • 두 단어의 벡터의 방향과 크기가 비슷하기 때문에 둘은 의미가 비슷한 단어라고 할 수 있다.
    • 반대로 두 벡터의 방향과 크기가 크게 다르다면 유사도가 낮다고 할 수 있다.

그렇다면 누가 어떤 기준으로 "'강아지'와 '시츄'는 비슷해"라고 좌표를 정한 걸까? 답은 아무도 정해 주지 않고 AI가 스스로 알아냈다는 것이다. 임베딩 모델이 수십 TB의 텍스트로 빈칸 맞추기를 수 억번 반복하면서 좌표를 학습한다고 하는데, 임베딩 모델을 학습시킬 것은 아니므로 이 부분은 그냥 넘어간다.

 

임베딩 모델이 생성한 벡터는 벡터 저장소에 저장되며, 이곳에서 효율적인 검색이 이루어 진다.

  • 시각화: 수많은 벡터 데이터를 2차원 평면 위에 뿌려 보면, 의미가 유사한 데이터끼리 군집(클러스터)을 이룬다.
  • 유사도 검색: 사용자의 질문(Query)을 벡터로 변환한 뒤, 저장소 내에 가장 거리가 가까운 벡터를 찾아낸다.

임베딩을 통해 벡터화한 데이터를 문서 검색(RAG)이나 안면 인식 등에 활용할 수 있다. 여기서 주의해야 할 점은, 임베딩 모델마다 데이터를 해석하는 방식과 출력하는 방식이 다르기 때문에 저장할 때 사용한 모델과 검색할 때 사용하는 모델이 반드시 같아야 한다는 것이다.

벡터 저장소 (Vector Store)

벡터 저장소는 임베딩 모델을 통해 생성된 벡터 값을 저장하고 이를 기반으로 유사도 검색을 수행하는 특수한 DB다.
  • 검색 방식: 데이터 간의 수치적 거리를 계산해 가장 유사한 데이터를 찾음
  • 거리 계산 지표
    • Euclidean(L2) Distance: 정규화된 두 벡터 사이의 물리적 직선 거리
    • Cosine Distance: 두 벡터가 이루는 각도를 이용한 계산
구분 유클리디언 유사도 코사인 유사도
측정 기준 두 점 사이의 직선 거리 두 벡터 사이의 각도
핵심 요소 데이터의 값(크기) 자체 데이터의 방향(패턴)
값의 범위 0 ~ (거리가 멀수록 유사도 낮음) -1 ~ 1 (1에 가까울수록 유사도 높음)
주요 용도 군집화(K-Means), 수치형 데이터 비교 텍스트 분석(NLP), 추천 시스템
크기 영향 데이터 크기에 민감함 데이터 크기에 영향을 받지 않음
  • 데이터 저장 과정
    1. 애플리케이션에서 저장할 데이터를 임베딩 모델로 전달
    2. 임베딩 모델을 통해 텍스트를 고차원 수치 배열(Vector)로 변환
    3. 변환된 벡터를 Vector Store에 저장
  • 유사도 검색 과정
    1. 사용자가 질문(검색 데이터)을 던지면 애플리케이션이 수집함
    2. 저장 시와 동일한 임베딩 모델을 사용해 질문을 벡터로 변환
    3. 생성된 쿼리 벡터와 저장소 내 벡터들 간의 거리를 계산해 유사한 항목을 찾음
    4. 가장 유사도가 높은 데이터를 기반으로 검색 결과로 애플리케이션에 반환

🧩 검색 증강 생성 (RAG)

검색 증강 생성(RAG)은 대규모 언어 모델의 출력을 최적화하여 응답을 생성하기 전에 훈련 데이터 소스 외부의 신뢰할 수 있는 기술 자료를 참조하도록 하는 프로세스를 의미한다.

RAG의 등장 배경

LLM에는 다음과 같은 한계들이 존재한다.

  • 지식 단절(Cut-Off): 학습된 시점 이후의 최신 정보를 알 지 못함 (예를 들어 Gemini 모델은 2025년 1월까지의 데이터만 학습됨)
  • 할루시네이션: 모르는 정보에 대해 그럴 듯한 거짓말을 생성함. 아주 그냥 입만 열면 거짓말이 자동으로 나옴
  • 컨텍스트 윈도우 한계: 회사 문서 수 천장을 통째로 올려도 컨텍스트 윈도우 크기는 정해져 있어 다 읽을 수 없음
  • 보안 및 특화 도메인: 기업 내부 데이터나 비공개 전문 지식은 학습 데이터에 포함되지 않음

이를 해결하기 위해 모델 자체를 고치는 파인 튜닝 대신, 외부 지식을 실시간으로 참조하는 RAG 방식이 주로 사용된다.

구분 파인 튜닝(Fine-tuning) 검색 증강 생성(RAG)
작동 방식 모델 자체를 추가 학습(가중치 업데이트) 외부 데이터베이스에서 정보 검색
비용/자원 고성능 GPU, 대량의 데이터, 긴 훈련 시간 필요 상대적으로 저렴, 기존 API와 벡터 DB 활용
최신성 데이터 업데이트마다 재학습 필요 DB 정보만 바꾸면 즉시 최신화 가능
강점 응답 일관성, 지연 시간 감소, 보안 유리 정확한 정보 제공, 할루시네이션 억제
  1. Retrieve (검색)
    • Embedding: 사용자의 질문(Query)을 컴퓨터가 이해할 수 있는 수치 데이터(Vector)로 변환
    • Vector DB: 변환된 벡터를 지식 저장소와 대조해 질문과 가장 유사도가 높은 컨텍스트를 찾아냄
  2. Augment (증강)
    • 찾아낸 관련 정보(Context)를 사용자의 원래 질문과 합쳐 프롬프트를 재구성함
    • 이 과정에서 AI에게 "네가 아는 것 외에, 아래 제공하는 정보를 참고해서 대답해"라는 지시가 포함됨
  3. Generate (생성)
    • LLM은 자신의 사전 학습 지식 + 증강된 프롬프트 내의 문맥을 결합해 최종 답변을 생성함
    • 결과적으로 사용자에게는 가장 최신의 정확한 답변이 전달될 수 있음

쉽게 비유하자면, 질문이 들어오면 수천 권의 책이 꽂힌 서재를 통째로 책상에 올리는 게 아니라 질문이랑 관련된 책 몇 권만 쏙 뽑아서 책상에 올리고, AI는 그 몇 권만 보고 답하는 것이 RAG의 핵심이다.

 

그런데 '관련된 책'을 어떻게 찾는 다는 걸까? 서재의 모든 책들을 미리 의미 좌표로 바꿔서 꽂아 두었고 질문도 좌표로 변환해 질문 좌표와 가장 가까운 꺼낸다.

 

넓은 의미로 보면 ChatGPT한테 PDF 하나 던져 주고 "이거 보고 대답해"라고 하는 것도 RAG의 일종이다. 그런데 Gemini는 PDF 첨부하면 이름만 보이고 내용은 안 보인다고 징징거리던데 조만간 구독을 해지하든지 해야겠다😑

 

아무튼 RAG 환경을 구축하면 다음과 같은 장점이 있다.

  • 할루시네이션 감소: 어느 자료를 보고 답했는지 출처도 같이 보여줄 수 있다.
  • AI 학습 비용 X
  • 컨텍스트 윈도우를 아낄 수 있음

물론 RAG가 만능지사는 아니다. 서재에서 엉뚱한 책을 가져오면 그걸 보고 또 틀리게 대답한다. 지 멋대로 지어내는 것을 줄이는 거지 완전히 없애지는 못하기 떄문에 "잘 찾는 것"이 중요하다.

데이터 엔지니어링 (ETL)

RAG는 LLM이 학습하지 못한 외부 데이터를 참조해 답변의 정확성을 높이는 기술이다. Spring AI에서는 이를 두 가지 시점으로 나눈다.

  • Offline: 사용자의 질문이 있기 전 외부 소스로부터 데이터를 추출 변환해 벡터 저장소에 미리 적재하는 과정 (via ETL 파이프라인)
  • Runtime: 사용자가 질문을 하면 벡터 저장소에서 관련 데이터를 검색(R)하고, 이를 프롬프트에 포함(A)하여 LLM이 답변을 생성(G)하는 과정
ETL 파이프라인은 다양한 출처의 데이터를 수집(추출)하고, 비즈니스 목적에 맞게 정제 및 표준화(변환)한 뒤, 분석 및 활용을 위해 중앙 저장소(적재)로 전송하는 자동화된 데이터 처리 프로세스를 의미한다.
단계 컴포넌트 주요 역할
Extract DocumentReader PDF, Word, URL 등 다양한 소스에서 텍스트를 추출해 Document 객체 생성
Transform DocumentTransformer 문서를 작은 조각(Chunk)으로 분할하거나 키워드/요약 등 메타데이터 추가
Load DocumentWriter 변환된 Document 조각들을 벡터 저장소에 최종 적재

Naive RAG

Naive RAG는 가장 기본적인 RAG 구조로, 다음과 같은 두 가지 시퀀스로 구성된다.

  • 문서 적재 시퀀스: 문서 읽기 → 청크 분할 → 임베딩 생성 → VectorStore 저장
  • 질문 시퀀스: 사용자 질문 → 질문 임베딩 → VectorStore 유사도 검색 → 관련 문서 반환 → 프롬프트 컨텍스트 주입 → 답변 생성
청크(Chunk)는 방대한 양의 원본 문서를 AI가 처리하기 쉽도록 잘게 쪼개어 놓은 작은 텍스트 조각을 의미한다.

 

상술했지만 LLM은 한 번에 읽을 수 있는 최대 길이(컨텍스트 윈도우)가 정해져 있어 긴 문서를 통째로 읽을 수 없기 때문에, 문서를 짧은 조각으로 나누어 두면 사용자의 질문과 가장 관련성이 높은 핵심 정보만 빠르고 정확하게 찾아낼 수 있다.

  • 작은 청크: 아주 구체적이고 정밀한 검색이 가능하지만, 전체적인 맥락이 끊겨 답변이 피상적일 수 있음
  • 큰 청크: 배경지식과 문맥을 충분히 담을 수 있지만, 불필요한 정보가 섞일 확률이 높고 검색 속도가 느려질 수 있음

대표적인 청킹 전략에는 다음과 같은 방식들이 있다.

 

  • 단순 길이 기반(Fixed-size): 글자 수나 토큰 수(예: 512 토큰)를 기준으로 일정하게 문서를 자르는 방식
  • 의미 기반(Semantic): 문맥과 의미가 끊기지 않도록 문단이나 주제 단위로 문서를 분할하는 방식
  • 구조 기반(Document-based): PDF나 문서의 레이아웃, 마크다운 구조(제목, 표 등)를 인식하여 의미 있는 블록 단위로 나누는 방식

Naive RAG는 기본형이긴 하지만 운영 단계에서는 충분하지 못할 수 있다. 질문이 애매하면 검색 쿼리가 약해지고, 유사도 검색이 항상 만능은 아니다. 검색 결과가 프롬프트에 들어가도 LLM이 뻘짓을 할 수도 있다.

점검 항목 확인 질문
문서 품질 검색할 문서 자체가 최신인가?
청크 전략 한 청크에 하나의 의미 단위가 들어가는가?
메타데이터 부서, 버전, 날짜, 문서 타입을 저장했는가?
검색 쿼리 사용자 질문을 그대로 검색해도 충분한가?
응답 검증 답변이 검색 문서에 근거하고 있는가?

Spring AI RAG의 구성요소

구성요소 역할
DocumentReader 문서 읽기
TokenTextSplitter 청크 분할
EmbeddingModel 벡터 변환
VectorStore 저장 및 검색
QuestionAnswerAdvisor 컨텍스트 주입
ChatClient 모델 호출

 

여기서 QuestionAnswerAdvisor는 Spring AI에서 RAG 패턴을 가장 쉽게 구현할 수 있도록 돕는 Advisor다. 사용자의 질문을 기반으로 VectorStore에서 관련 문서를 자동으로 검색하고, 이를 프롬프트의 컨텍스트에 포함시켜 LLM이 정확한 답변을 생성하도록 유도한다.

public RagChatService(ChatClient.Builder builder, VectorStore vectorStore) {
    this.chatClient = builder
            .defaultSystem("""
                    제공된 문서 컨텍스트를 우선하여 답변하세요.
                    문서에서 근거를 찾을 수 없으면 모른다고 답하세요.
                    답변 마지막에는 참고한 근거를 짧게 요약하세요.
                    """)
            .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
            .build();
}

 

 

여기서 검색의 정교함을 높이기 위해 SearchRequest를 사용해 유사도 임계치, 검색 개수, 필터 조건 등을 정의할 수 있다.

SearchRequest searchRequest = SearchRequest.builder()
    .similarityThreshold(0.5)     // 유사도 0.5 이상
    .topK(3)                      // 상위 3개 문서
    .filterExpression("source == '헌법'") // 메타데이터 필터링
    .build();

QuestionAnswerAdvisor questionAnswerAdvisor = QuestionAnswerAdvisor
    .builder(vectorStore)
    .searchRequest(searchRequest)
    .build();

 

QuestionAnswerAdvisor가 RAG의 과정을 하나로 묶은 통합형이라면, RetrievalAugmentationAdvisor는 RAG의 각 단계를 모듈화하여 설계된 Advisor이다.

  • 특징: 각 단계를 독립적인 컴포넌트로 분리하여 런타임 시 유연하게 조합 가능
  • 구저적 차이: 유사도 검색 기능을 직접 포함하지 않고 외부 모듈을 주입받아 실행함
구분 QuestionAnswerAdvisor RetrievalAugmentationAdvisor
특징 기본적이고 표준적인 RAG 구현 모듈화되고 세부적인 제어가 가능한 RAG
장점 설정이 간단하여 기본적인 RAG를 빠르게 구축할 때 유리 RAG 파이프라인의 각 구성 요소를 커스텀하거나 교체 가능
동작 방식 VectorStore 검색 → 검색된 문서를 요청에 추가 → 프롬프트 생성 질의 변환(Query Transformer), 문서 검색, 프롬프트 템플릿 등 각 단계를 개별 모듈로 나누어 세밀하게 제어
적합한 상황 빠르고 직관적인 질의응답 기능이 필요한 경우 언어 번역, 쿼리 압축/재작성 등의 고급 RAG 기법이 필요한 경우

[참고자료]

 

X의 BUGI님(@Bugi952)

AI 용어 공부 4화 - RAG AI가 모르는 걸 찾아서 답하는 법 지난 시간엔 "AI가 한 번에 읽을 수 있는 책상 크기" 컨텍스트 윈도우를 공부했음 오늘은 그 작은 책상으로 어떻게 방대한 지식을 다루는지,

x.com

 

벡터 데이터베이스란?

벡터 데이터베이스에 대한 모든 것을 확인하세요.

www.nvidia.com

 

RAG란? - 검색 증강 생성 AI 설명 - AWS

검색 증강 생성(RAG)이란 무엇이며, 기업에서 RAG AI를 사용하는 방법과 이유, AWS에서 RAG를 사용하는 방법에 대한 내용입니다.

aws.amazon.com

 

RAG 애플리케이션 개발을 위한 Chunking 최적화 | 요즘IT

PyCon Korea 2025에서 발표한 'RAG 애플리케이션 개발을 위한 Chunking 최적화' 세션을 기반으로, RAG의 핵심 요소인 '청킹(Chunking)'에 대해 깊이 있게 다루어 보고자 합니다. RAG 애플리케이션 개발에 관심

yozm.wishket.com