Agent Engineering으로 2시간만에 PDF RAG 만들기
- Agent Engineering으로 2시간만에 PDF RAG 만들기
Agent Engineering으로 2시간만에 PDF RAG 만들기
이번 프로젝트의 목적은 React나 FastAPI를 깊게 익히는 것이 아니다.
Agent Engineering 관점에서 PDF → 파싱 → 청킹 → 임베딩 → 검색 → 답변까지, RAG가 실제로 어떻게 흘러가는지 프로그램 화면에서 확인하는 것이 목표였다.
그래서 UI는 최소 기능만 두고, 문서 처리 파이프라인과 질의 시 프롬프트 조립(출처 포함) 흐름을 우선 구현했다. 스택은 React + FastAPI + Docker(PostgreSQL/pgvector)이며, 약 2시간 만에 동작하는 프로토타입까지 완성했다.
0. 한 줄 요약
| 항목 | 내용 |
|---|---|
| 학습 목적 | Agent Engineering — RAG 파이프라인을 코드와 화면으로 검증 |
| 비목적 | React/FastAPI 프레임워크 심화 학습 |
| 결과물 | PDF 업로드 → 처리 상태 확인 → 문서 기반 Q&A(출처 표시) |
| 소요 | 약 2시간 (프로토타입) |
| 스택 | React / FastAPI / PostgreSQL + pgvector / Docker |
1. Agent Engineering이란 무엇인가 (이번 글에서의 의미)
흔히 “에이전트”라고 하면 복잡한 멀티툴·자율 루프를 떠올리기 쉽다.
이번 연습에서는 범위를 좁혀, 아래를 Agent Engineering의 핵심 연습 포인트로 잡았다.
- 입력을 검색 가능한 지식으로 바꾸는 파이프라인
PDF 원문을 바로 LLM에 넣지 않고, 파싱 → 청킹 → 임베딩으로 검색용 지식 조각을 만든다. - 질문 시 “검색 → 컨텍스트 조립 → LLM 호출” 순서
LLM이 혼자 답하는 것이 아니라, 먼저 관련 청크를 찾고 그 내용을 근거로 답하게 한다. - 근거(출처)를 강제하는 응답 설계
답변과 함께 문서명·페이지·청크 스니펫을 보여, “어디서 왔는지”를 검증 가능하게 만든다.
즉, 예쁜 프론트엔드보다 에이전트가 어떤 데이터로 어떤 프롬프트를 만들어 답하는지를 보는 프로젝트다.
2. 화면으로 보는 전체 흐름
서비스는 화면 3개로 끝난다. 의도적으로 단순하다.
2-1. 메인 — 두 가지 진입점만
문서 업로드와 채팅 시작 링크로만 구성했다.
“무엇을 할 수 있는가”만 보이게 하고, RAG 본론은 문서 관리·채팅으로 넘긴다.

| 버튼 | 역할 |
|---|---|
| 문서 업로드하기 | 문서 관리 화면으로 이동 (지식 적재) |
| 채팅 시작하기 | 질의 화면으로 이동 (지식 활용) |
Agent Engineering 관점에서는 이 두 버튼이 곧 Knowledge Ingestion과 Retrieval + Generation 진입점이다.
2-2. 문서 관리 — 파싱 → 청킹 → 임베딩
PDF를 올리면 서버가 곧바로 긴 처리를 기다리지 않고, 파이프라인을 돌려 상태를 갱신한다.
화면 안내 문구 그대로 파싱 → 청킹 → 임베딩 순이다.

| 단계 | 하는 일 | Agent 관점 |
|---|---|---|
| 파싱 | PDF에서 텍스트·페이지 정보 추출 | 원본 → 기계가 읽을 수 있는 텍스트 |
| 청킹 | 토큰/문자 단위로 조각 내고 페이지 메타 보존 | LLM 컨텍스트에 넣을 검색 단위 생성 |
| 임베딩 | 각 청크를 벡터로 변환 후 pgvector 저장 | 의미 기반 검색이 가능한 지식 인덱스 |
예시처럼 블러온-backend.pdf(18p)가 완료가 되면, 이제 그 문서는 채팅의 검색 대상이 된다.
2-3. 채팅 — RAG 검색 후 응답 프롬프트 생성
질문을 보내면 서버는 (1) 질문을 임베딩하고 (2) 유사 청크를 검색한 뒤 (3) 검색 결과를 컨텍스트로 LLM 프롬프트를 만들고 (4) 답변 + 출처를 반환한다.

질문 예: 패키지 구조 알려줘.
응답에는 디렉터리 트리와 함께 (출처: 블러온-backend.pdf, p.4)가 붙고, 하단 출처 영역에 검색된 페이지·스니펫이 노출된다.
이 화면이 이번 프로젝트의 핵심 검증 지점이다.
- LLM이 “아는 척” 하는 게 아니라
- RAG 데이터(검색된 청크)를 근거로 프롬프트를 조립했는지
- UI에서 출처로 바로 확인할 수 있다.
3. 시스템 아키텍처 (최소 구성)
[React SPA]
업로드 화면 ──┐
채팅 화면 ───┤
▼
[FastAPI]
┌────┴────┐
│ │
업로드 API 질의 API
│ │
▼ ▼
파일 저장 질문 임베딩
documents │
status=pending │
│ ▼
▼ pgvector 유사도 검색
비동기 파이프라인 │
파싱→청킹→임베딩 ▼
│ 검색 청크 + 질문
▼ → LLM 프롬프트
PostgreSQL │
+ pgvector ▼
(chunks/embeddings) 답변 + 출처 → React
| 구성 요소 | 역할 | 이번 학습에서의 비중 |
|---|---|---|
| React | 업로드·상태·채팅·출처 표시 | 낮음 (확인용 UI) |
| FastAPI | API, 파이프라인 오케스트레이션, RAG 프롬프트 조립 | 중간 (흐름 연결) |
| PostgreSQL + pgvector | 청크·벡터·문서 상태 저장 | 높음 (검색 근거 저장소) |
| Docker | 로컬에서 DB 등 의존성 빠르게 기동 | 낮음 (환경) |
| LLM / Embedding API | 벡터화·최종 답변 생성 | 높음 (생성 단계) |
대용량 PDF는 업로드 API를 오래 붙잡지 않도록, 아키텍처상 비동기 태스크(큐/워커) 분리를 권장한다.
프로토타입에서는 빠르게 돌리는 쪽이 우선이었고, “상태값으로 파이프라인 진행을 보여 주는 것”이 학습 목표에 더 중요했다.
4. RAG 파이프라인을 Agent 관점으로 다시 보기
4-1. Knowledge Ingestion (지식 적재)
PDF 업로드
→ documents 생성 (status = pending)
→ 파싱 (텍스트 + 페이지)
→ 청킹 (overlap, page_number 보존)
→ 임베딩 (chunk → vector)
→ documents.status = ready
| status (예) | 의미 |
|---|---|
pending |
업로드됨, 처리 대기 |
parsing / chunking / embedding |
단계별 진행 중 |
ready |
검색·질의 가능 |
failed |
파싱 실패 등 — 사유 확인 |
왜 청킹이 중요한가?
한 PDF 전체를 매번 프롬프트에 넣을 수 없다. 토큰 한도와 비용 때문이다.
청크는 “에이전트가 나중에 집어올 수 있는 지식 단위”이고, 페이지 메타는 “출처를 사람에게 보여줄 라벨”이다.
4-2. Retrieval + Generation (검색 증강 생성)
사용자 질문
→ 동일 임베딩 모델로 질문 벡터화
→ pgvector top-k 유사도 검색
→ 관련 chunk 텍스트/문서명/페이지 조회
→ (검색 결과 + 질문)으로 프롬프트 구성
→ LLM 호출
→ 답변 + source_chunk_ids (출처) 반환
프롬프트에 넣는 컨텍스트는 “모델이 잘 아는 일반 지식”이 아니라 방금 검색한 문서 조각이다.
그래서 답변 아래에 출처 스니펫을 붙이면, 학습자(또는 사용자)가 에이전트의 근거 경로를 감사(audit) 할 수 있다.
4-3. 이번 프로토타입에서 의도적으로 줄인 것
| 항목 | 이유 |
|---|---|
| 화려한 UI / 디자인 시스템 | 학습 초점이 파이프라인이므로 |
| OCR(스캔 PDF) | MVP 범위 밖 — 텍스트 PDF 위주 |
| 복잡한 멀티 에이전트 루프 | 단일 RAG 흐름을 먼저 체감 |
| 벤더 고정 | 임베딩/LLM은 교체 가능한 구조로 두고 흐름만 검증 |
5. 데이터 모델 (검색·출처를 위해 필요한 최소 스키마)
Agent Engineering에서 “프롬프트에 무엇을 넣을 수 있는가”는 곧 어떤 테이블에 무엇을 남겼는가와 같다.
| 테이블 | 역할 |
|---|---|
documents |
파일 메타, 처리 status |
chunks |
분할 텍스트 + page_number 등 |
embeddings |
chunk와 1:1 벡터 (vector(N)) |
conversations / messages |
대화 기록, source_chunk_ids로 출처 추적 |
출처 UI는 messages.source_chunk_ids → chunks → documents.filename + page_number 조회로 만들 수 있다.
채팅 화면의 “출처: 블러온-backend.pdf, p.2 / p.4”가 바로 이 경로다.
6. 2시간 프로토타입에서 얻은 것
- Agent Engineering은 UI보다 파이프라인 설계다
업로드·상태·채팅 3화면만으로도 “지식이 어떻게 쌓이고, 질문이 어떻게 근거를 고르는가”를 설명할 수 있다. - RAG의 성패는 검색 품질 + 출처 강제에 가깝다
답만 예쁘면 검증이 어렵다. 출처 chunk를 UI에 노출하니, 잘못된 검색도 바로 드러난다. - 스택은 수단이다
React/FastAPI/Docker는 흐름을 돌리기 위한 도구였고, 학습 질문은 항상 “이 단계에서 에이전트는 무엇을 저장·검색·조립하는가?”였다.
7. 다음에 다듬을 항목
프로토타입 이후 Agent Engineering을 한 단계 올리려면 아래가 자연스러운 확장이다.
| 우선순위 | 항목 | 의도 |
|---|---|---|
| Should | 멀티턴 대화 컨텍스트 | 후속 질문에 이전 맥락 유지 |
| Should | 임베딩/LLM 실패 재시도 | 파이프라인 신뢰성 |
| Should | 답변 스트리밍 | 체감 지연 개선 |
| Could | 문서 범위 선택(단일/전체) | 검색 스코프 제어 |
| Could | 전용 태스크 큐(Redis 등) | 대용량 PDF·동시 업로드 |
8. 마치며
Agent Engineering으로 2시간 만에 PDF RAG 프로토타입을 만들었다.
핵심은 세 가지다.
- 지식 적재: PDF를 파싱·청킹·임베딩해 pgvector에 검색 가능한 형태로 넣는다.
- 질의 경로: 질문 → 유사도 검색 → 컨텍스트 조립 → LLM → 출처 포함 응답.
- 학습 초점: React/FastAPI가 아니라, 에이전트가 어떤 근거로 프롬프트를 만드는지를 화면으로 확인한다.
다음에도 비슷한 연습을 한다면, UI를 늘리기보다 청킹 전략·검색 top-k·프롬프트 템플릿·출처 품질을 바꿔 가며 Agent Engineering 감각을 키우는 편이 이득이 크다.
참고
- 프로젝트 PRD / Architecture 초안 (
pdf-rag-service/PRD.md,ARCHITECTURE.md) - RAG (Retrieval-Augmented Generation) 개념
- pgvector