이 문서는 FastAPI + LangChain + OpenAI Embeddings + GPT-5 + ChromaDB 조합으로
Markdown 문서를 기반으로 한 RAG(Retrieval-Augmented Generation) 시스템을 구현하기 위한 입문 → 실전용 전체 가이드입니다.
기술 스택 현황
- FastAPI 기반 백엔드를 이미 사용 중
- LangChain / RAG 개념은 알고 있지만 구조가 정리되지 않은 상태
- 향후 pgvector(PostgreSQL) 기반으로 확장할 계획
1. RAG란 무엇인가 (개념 정리)
RAG는 LLM이 외부 지식을 직접 기억하는 대신,
필요할 때 검색(Retrieval) 해서 맥락(Context) 으로 주입받아 응답을 생성하는 구조입니다.
전통적인 LLM
질문 → LLM → 응답 (모델 내부 지식만 사용)
RAG 구조
질문
↓
Embedding(질문)
↓
Vector DB 검색
↓
관련 문서 조각(Context)
↓
LLM (GPT-5)
↓
응답 + 출처
RAG의 핵심 포인트는 “검색 품질” 이며,
그 품질을 결정하는 요소는 다음 3가지입니다.
- 문서를 어떻게 쪼갰는가 (Chunking)
- 어떤 방식으로 검색했는가 (Retrieval)
- 검색 결과를 어떻게 프롬프트에 넣었는가 (Prompting)
2. 전체 아키텍처 개요
Markdown Docs
↓
Loader
↓
Text Splitter
↓
OpenAI Embedding
↓
ChromaDB (Vector Store)
↓
Retriever
↓
GPT-5
FastAPI에서는 이 과정을 Service Layer 로 감싸서 제공합니다.
3. 프로젝트 구조 예시 (권장)
app/
├─ core/
│ └─ config.py
├─ rag/
│ ├─ loaders/
│ │ └─ markdown_loader.py
│ ├─ splitters/
│ │ └─ markdown_splitter.py
│ ├─ vectorstore/
│ │ └─ chroma_store.py
│ ├─ retriever.py
│ ├─ service.py
│ └─ schemas.py
└─ api/v1/
└─ rag.py
이후 pgvector로 이전해도 service / retriever 구조는 그대로 유지 가능
4. Step 1 — Markdown 문서 로딩
목표
- .md 파일을 읽어서
- 본문 + 메타데이터 형태로 변환
저장해야 할 메타데이터 예시
- 파일 경로
- 문서 제목
- 상위 헤더(H1/H2)
- 문서 종류 (manual, faq, spec 등)
이유
→ 나중에 출처 표시 / 필터 검색에 필수
5. Step 2 — Chunking 전략 (가장 중요)
왜 Chunking이 중요한가?
LLM은 부분 문맥만 받아도 이해할 수 있지만,
너무 짧으면 의미가 깨지고,
너무 길면 검색 정확도가 떨어집니다.
권장 기준 (Markdown 기준)
| 항목 | 값 |
|---|---|
| Chunk 크기 | 800 ~ 1200 tokens |
| Overlap | 10~15% |
| 분리 기준 | Header → Paragraph → Sentence |
이상적인 Chunk 예시
- 하나의 개념 / 정의 / 절차가 혼자서 의미를 가짐
- “이 Chunk 하나만 읽어도 답을 만들 수 있다” 수준
6. Step 3 — Embedding 생성
Embedding이란?
텍스트를 숫자 벡터로 변환한 것
- 의미가 비슷한 문장 → 벡터 거리도 가까움
- 검색은 “문장 비교”가 아니라 “벡터 거리 계산”
OpenAI Embedding 사용 흐름
- Chunk 텍스트 입력
- Embedding 모델 호출
- 고정 차원의 벡터 반환
- Vector DB에 저장
7. Step 4 — ChromaDB 이해하기
ChromaDB란?
- 임베딩 검색 전용 데이터베이스
- 로컬 또는 서버 형태로 사용 가능
- LangChain과 매우 자연스럽게 연동
장점
- 빠른 초기 구축
- 스키마 설계 부담 없음
- 로컬 개발에 최적
단점
- 운영/백업/HA는 직접 구성해야 함
- 트랜잭션 기반 시스템에는 한계
8. ChromaDB vs PostgreSQL(pgvector)
| 항목 | ChromaDB | PostgreSQL + pgvector |
|---|---|---|
| 초기 난이도 | 매우 낮음 | 중간 |
| 운영 안정성 | 보통 | 매우 높음 |
| 트랜잭션 | 약함 | 강함 |
| 운영 경험 | 별도 학습 | 기존 Postgres 그대로 |
| 추천 단계 | 학습 / PoC | 실서비스 |
추천 전략
Chroma → pgvector 이전
Chunk 구조만 잘 설계하면 DB 교체는 어렵지 않습니다.
9. Step 5 — Retrieval 전략
기본 검색
- Similarity Search
- Top-K: 4~8
개선 전략
- MMR (중복 제거)
- Metadata Filter (카테고리 / 문서 타입)
- Reranker (추후)
10. Step 6 — Prompt 구성 원칙
System Prompt 예시 개념
- 제공된 문서만 사용
- 모르면 모른다고 답변
- 출처 포함
Context 주입 방식
[문서1]
...
[문서2]
...
Context가 프롬프트의 70% 이상 차지해도 정상입니다.
11. Step 7 — FastAPI Endpoint 설계
추천 API
문서 인덱싱
POST /rag/ingest
질의 응답
POST /rag/query
응답 구조 예시
{
"answer": "...",
"citations": [
{"source": "manual.md", "section": "3.2"}
]
}
12. AI Agent에 RAG 붙이는 방법
RAG를 도구(tool) 로 취급하세요.
Tool: search_docs
Input: query
Output: relevant_chunks
Agent는 판단만 합니다:
- “지식이 필요하다” → RAG 호출
- “대화만 필요하다” → 바로 응답
13. 품질 튜닝 체크리스트
- Chunk 크기 조절
- Overlap 증가/감소
- Top-K 변경
- Prompt 제한 강화
- Metadata 필터링
RAG 문제의 80%는 Chunking 문제입니다.
14. 다음 단계 (추천)
- pgvector 기반 이전
- Hybrid Search (BM25 + Vector)
- Reranker 모델 추가
- 출처 하이라이팅 UI
- 다중 문서 컬렉션 분리
마무리
이 문서를 기준으로 구현하면:
- 학습용 RAG → 실서비스 RAG 로 자연스럽게 확장 가능
- AI Agent 구조에도 무리 없이 통합 가능
다음 요청으로 추천하는 것:
- “이 구조 기반으로 실제 FastAPI 코드 스켈레톤 만들어줘”
- “Chroma → pgvector 마이그레이션 가이드”
- “LangGraph 기반 Agent + RAG 통합”