← Notes

RAG (Retrieval-Augmented Generation)

ai

개념

LLM은 학습 데이터에 없는 정보를 모른다. 내 노트, 사내 문서 같은 건 답할 수 없다.

RAG는 질문하기 전에 관련 문서를 검색해서 LLM에 같이 넘기는 것이다.

  • Retrieval — 관련 문서 검색
  • Augmented — 검색 결과를 프롬프트에 붙임
  • Generation — LLM이 그걸 보고 답변 생성

전부 주는 게 아니라 관련된 것만 골라서 준다. 노트가 200개여도 질문과 관련된 3~5개만 넘긴다.

전체 흐름

[사전 준비 — 한 번만]
문서 → 청킹 (적당한 크기로 자름) → 임베딩 (텍스트→벡터) → 벡터 DB에 저장

[질문할 때 — 매번]
질문 → 임베딩 → 벡터 DB에서 유사한 문서 검색 → 검색 결과 + 질문을 LLM에 전달 → 답변

임베딩

텍스트를 숫자 배열(벡터)로 변환하는 것. 의미가 비슷한 텍스트는 벡터도 비슷하다.

"접근 제어" → [0.023, -0.041, 0.087, ...]
"RBAC"     → [0.025, -0.039, 0.091, ...]  # 비슷한 벡터
"날씨"     → [-0.512, 0.331, -0.087, ...]  # 다른 벡터

그래서 "접근 제어"로 검색하면 "RBAC" 문서가 나온다. 키워드가 달라도 의미가 같으면 찾아준다.

임베딩 방식

OpenAI API 로컬 모델
비용 유료 무료
속도 네트워크 필요 즉시
품질 높음 (1536차원) 괜찮음 (384차원)
한국어 좋음 모델마다 다름

임베딩은 연산이 가벼워서 로컬로 충분하다. 문서 1만 개여도 CPU로 몇 분이면 끝남.

한국어 섞인 문서는 intfloat/multilingual-e5-small 같은 다국어 모델이 무난하다.

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("intfloat/multilingual-e5-small")
vector = model.encode("RBAC는 역할 기반 접근 제어로...")

벡터 DB

임베딩된 벡터를 저장하고 유사도 검색하는 DB. 일반 DB의 WHERE 대신 코사인 유사도로 검색한다.

  • ChromaDB — 로컬, 설치 간단, 개인 프로젝트에 적합
  • Pinecone — 클라우드, 대규모 서비스용
import chromadb

client = chromadb.PersistentClient(path="./chroma_data")
collection = client.get_or_create_collection("notes")

# 저장
collection.add(
    documents=["RBAC는 역할 기반 접근 제어..."],
    embeddings=[vector],
    metadatas=[{"title": "RBAC", "tags": "security"}],
    ids=["rbac_chunk_1"],
)

# 검색
results = collection.query(
    query_embeddings=[query_vector],
    n_results=3,
)

청킹

긴 문서를 적당한 크기로 잘라야 한다. 통째로 넣으면 검색 정확도가 떨어지고, 너무 잘게 자르면 맥락이 없어진다.

  • 고정 크기 — 500자씩 자르기. 단순하지만 문맥이 끊길 수 있음
  • 의미 단위 — 마크다운 ## 헤딩 기준으로 자르기. 구조화된 문서에 적합
  • 오버랩 — 앞뒤 100자씩 겹치게 자르기. 문맥 유지

RAG에서 코드로 짜는 부분 vs AI가 하는 부분

단계 누가 하나
파일 읽기 내 코드
frontmatter 파싱 내 코드
청킹 내 코드
텍스트 → 벡터 변환 임베딩 모델 (로컬 or API)
벡터 저장/검색 내 코드 (ChromaDB 사용)
검색 결과 보고 답변 생성 LLM API

AI가 하는 건 임베딩이랑 답변 생성 두 군데. 나머지는 전부 엔지니어가 설계하고 짠다.

새 문서 추가 시

RAG 자체는 읽기 전용 구조다. 새 문서가 추가되면 ingest 파이프라인을 다시 돌려야 한다.

새 노트 → 청킹 → 임베딩 → 벡터 DB에 추가

하지만 기존 문서가 이미 벡터로 있으니까, 새 문서와 기존 문서의 관계를 바로 파악할 수 있다. 이걸 활용하면 자동 태깅, 자동 연결 같은 Agent 기능을 만들 수 있다.

sunshinemoon · 2026