2일차 — RAG
📝 실시간 메모 노션 https://app.notion.com/p/KT-DS-3dc4b65410c88078986dc7773a805651 ↗강의자료 (PDF)
2일차 — RAG 강의자료 PDF입니다. 아래 링크에서 다운로드해 강의 중 함께 보시면 됩니다.
📎 2일차 — RAG 강의자료 (PDF) Project404 강의 · 2일차 — RAG ⬇ 다운로드실습 1 — Mini NotebookLM (개요)
교육용 Mini NotebookLM 을 8스텝으로 점진적으로 완성합니다. 스텝마다 바로 복사 가능한 개발 프롬프트 를 제공하며, 이전 스텝 결과물 위에 기능을 더해나가는 구조입니다.
- STEP 1 — MVP 뼈대 (문서 업로드 → 자동 처리 → 질문 → 답변)
- STEP 2 — RAG Inspector (Chunk · Embedding Vector 시각화)
- STEP 3 — Chunk Lab (Chunk Size/Overlap 실험 · Re-index)
- STEP 4 — Metadata Manager (department · security_level · allowed_roles)
- STEP 5 — Retrieval Debug (Top-K · Threshold · 검색 결과 표시)
- STEP 6 — Citation (근거 표시 · Source 번호 매핑)
- STEP 7 — 권한 기반 Retrieval (Role Selector + Metadata Filter)
- STEP 8 — Index Manager (Hash 감지 · Re-index · 버전 관리)
BAAI/bge-m3 (한국어 우수 · 1024-D) · Anthropic Claude API. 지원 문서: PDF · DOCX · XLSX · TXT · MD. 업로드 경로: data/uploads/, 벡터DB: data/chroma/. .env 에 EMBEDDING_MODEL=BAAI/bge-m3 로 지정.📎 실습용 문서 7종 — Mini NotebookLM 에 업로드해 RAG 를 실험할 다양한 형식의 사내 문서. STEP 4(Metadata) · STEP 7(권한) 실험용으로 공개/기밀 · 부서별 문서를 섞어 두었습니다. STEP 8(Re-index) 실험을 위해 employee_policy 는 원본 과 수정본 두 벌을 제공합니다.
🗺️ 스텝별 시나리오 마스터 표 — 강의 진행 중 이 표만 열어놓고 위에서 아래로 내려가면 됩니다.
| STEP | 핵심 목적 | 물어볼 질문 / 조작 | 확인할 변화 |
|---|---|---|---|
| 1 | 완성된 RAG 를 써본다 | 1년 이상 근속자의 기본 연차는 며칠이야? | 15일 · 문서 기반 답변 |
| 2 | Chunk / Vector 구조 확인 | 01_employee_policy.pdf 열어 Chunk #n 클릭 | 1 Doc → N Chunks → N Vectors · 1024-D 실제 숫자 배열 |
| 3 | Chunk Size 변경의 영향 | 동일 질문을 800/100 → 500/50 에서 반복 | Chunks·Vectors 수, Similarity, Retrieved 내용 변화 |
| 4 | Vector vs Metadata 구분 | 문서별 Metadata 입력 (HR / CONFIDENTIAL / allowed_roles) | Vector 그대로 · Metadata 만 변경 (재임베딩 X) |
| 5 | Top-K / Threshold 실습 | 1년 이상 근속자 연차와 신청 마감일 (복수 문서) | K=1→3→5 통과/제외 결과 변화 |
| 6 | 답변 근거 확인 (Citation) | 위와 동일한 복수 문서 질문 | [1][2] 클릭 → 실제 PDF/DOCX Chunk 원문 연결 |
| 7 | 권한 필터 (Retrieval 前) | CEO 연간 기본보상과 성과보너스 상한은? · Role 을 DEV→HR→CEO 순 | DEV 차단 · HR/CEO 만 검색 |
| 8 | 문서 변경 → Re-index | 동일 질문 · v1 → v2 파일 교체 → Re-index | 15일 → 16일 · Hash/Version/Indexed At 변화 |
🔁 수업 내내 재사용할 4개 핵심 질문 — 매 스텝 같은 질문의 내부 동작이 하나씩 드러납니다.
- A — 1년 이상 근속자의 기본 연차는 며칠이야? (기본 RAG · Chunk · Re-index 실험용)
- B — 직원이 1년 넘게 근무했다면 쉬는 날을 기본적으로 며칠 받을 수 있어? (Semantic Search 검증 — 문장 표현이 달라도 찾나?)
- C — 1년 이상 근속자의 기본 연차는 며칠이고, 그 연차는 최소 언제까지 신청해야 해? (Top-K · 복수 Source · Citation 실험용)
- D — CEO 의 연간 기본보상과 성과보너스 상한은 얼마야? (Metadata 권한 필터 실험용)
실습 1 · STEP 1 — MVP 뼈대
가장 먼저 문서 업로드 → 자동 처리 → 질문 → 문서 기반 답변 이 브라우저에서 실제 동작하는 최소 형태를 만듭니다.
Python + Flask + Vanilla HTML + SQLite 기반으로 교육용 Mini NotebookLM 프로젝트를 처음부터 만들어줘.
현재 폴더에는 프로젝트가 없다고 가정하고 필요한 파일과 폴더를 모두 생성한다.
기술 스택:
- Python
- Flask
- Vanilla HTML / CSS / JavaScript
- SQLite
- ChromaDB
- sentence-transformers
- Anthropic Claude API
지원 문서: PDF · DOCX · XLSX · TXT · MD
Embedding Model: BAAI/bge-m3 (한국어 대응 · 1024차원. .env 에 EMBEDDING_MODEL=BAAI/bge-m3 로 지정)
Vector DB: ChromaDB Persistent Mode
Claude API Key: .env 파일의 ANTHROPIC_API_KEY 사용
업로드 경로: data/uploads/
Vector DB 경로: data/chroma/
기본 Chunk 설정:
chunk_size = 800
chunk_overlap = 100
사용자가 문서를 업로드하면 자동으로 다음 Pipeline을 실행한다.
Document Upload → Text Extraction → Chunking → Embedding → ChromaDB 저장
사용자가 질문하면:
Question → Query Embedding → ChromaDB Vector Search → 관련 Chunk 검색 → 검색된 Chunk를 Claude Context에 전달 → Claude 최종 답변
전체 문서를 매번 Claude에게 보내지 않는다. 반드시 Vector Search에서 찾은 관련 Chunk만 Claude에게 전달한다.
UI는 NotebookLM처럼 3단 구조로 만든다.
왼쪽 Sources: 문서 업로드 · 업로드된 문서 목록 · 문서 삭제
가운데 Chat: 질문 입력 · 사용자 질문 · Claude 답변
오른쪽 System Status: Documents · Chunks · Vectors · Embedding Model · Vector DB 상태 · Claude 연결 상태
SQLite에는 최소 다음 테이블을 만든다.
documents: id · filename · original_filename · file_type · file_path · file_size · file_hash · status · created_at · updated_at
chunks: id · document_id · chunk_index · content · page_number · character_count · created_at
Claude System Prompt에는 다음 규칙을 포함한다.
- 제공된 CONTEXT를 근거로 답변한다.
- CONTEXT에 없는 내용을 임의로 추측하지 않는다.
- 찾을 수 없으면 "제공된 문서에서 해당 내용을 찾을 수 없습니다."라고 답한다.
이번 STEP에서는 내부 RAG Debug 기능은 만들지 않는다.
우선 가장 중요한 것은: 문서 업로드 → 자동 처리 → 질문 → 문서 기반 답변 이 실제 브라우저에서 정상 동작하는 것이다.
필요한 requirements.txt와 README.md도 작성한다.
중간에 질문하지 말고 필요한 구조를 합리적으로 판단해서 완성한다.
🧪 STEP 1 테스트 시나리오 — 먼저 완성된 RAG 를 써본다
- 사전 준비 — 실습용 문서 중 01·02·04·05·06 6개 업로드 (03은 STEP 7 에서 추가)
- Q1 (정확 매칭) —
1년 이상 근속자의 기본 연차는 며칠이야?· 기대: 15일 - Q2 (표현 변형 · Semantic Search 맛보기) —
직원이 1년 넘게 근무했다면 쉬는 날을 기본적으로 며칠 받을 수 있어?· 기대: 15일 - Q3 (다른 문서) —
일반 연차는 최소 언제까지 신청해야 해?· 기대: 최소 3영업일 전 - Q4 (복수 문서 결합) —
1년 이상 근속자의 기본 연차는 며칠이고, 그 연차는 최소 언제까지 신청해야 해?· 기대: 15일 · 최소 3영업일 전
실습 1 · STEP 2 — RAG Inspector
STEP 1 결과물에 업로드된 문서가 몇 개의 Chunk 로 나뉘고, 각 Chunk 가 어떤 1024차원 Vector 로 저장됐는지 브라우저에서 직접 확인하는 화면을 추가합니다.
현재 STEP 1에서 만든 Mini NotebookLM의 모든 기능을 유지하면서 RAG Inspector 기능을 추가해줘.
새 메뉴: RAG Inspector
목적: 업로드된 하나의 문서가 실제로 몇 개의 Chunk로 분리되어 있고 각 Chunk가 어떤 Embedding Vector로 ChromaDB에 저장되어 있는지 브라우저에서 직접 확인하는 것이다.
문서를 선택하면 상단에 다음 정보를 표시한다.
- Filename
- Original Characters
- Chunk Size
- Chunk Overlap
- Total Chunks
- Embedding Model
- Embedding Dimension
- Vector Count
예: employee_policy.pdf · 38,420 chars · 800/100 · 47 chunks · BAAI/bge-m3 · 1024 dim · 47 vectors
아래에는 해당 문서의 모든 Chunk를 표시한다.
예: Chunk #1 (Page 1, 782 chars), Chunk #2 (Page 1, 796 chars), Chunk #18 (Page 12, 731 chars) ...
Chunk 하나를 클릭하면 우측 상세 Panel을 연다. 다음 내용을 보여준다.
- Chunk ID · Chunk Index · Filename · Page · Character Count · Original Text
- Embedding Model · Embedding Dimension
- Vector Preview: 실제 ChromaDB에 저장되어 있는 해당 Chunk의 Embedding Vector
기본적으로 앞 20개 값만 표시. 'View Full Vector' 버튼으로 전체 1024-D 확인.
중요: 임의의 Vector 샘플을 만들어 보여주지 말고 실제 ChromaDB에 저장된 값을 사용한다.
화면 상단에 Pipeline 도식도 표시: Document → Chunks → Selected Chunk → Embedding → 1024-D Vector
문서 하나가 Vector 하나가 되는 것이 아니라 Chunk #1 → Vector #1, Chunk #2 → Vector #2 형태라는 것을 UI에서 명확히 확인할 수 있게 한다.
기존 Chat / Sources 기능은 그대로 유지한다.
🧪 STEP 2 테스트 시나리오 — 방금 답을 어떻게 찾았는지 뜯어본다
- 조작 1 — RAG Inspector 에서
01_employee_policy.pdf선택 → 상단 요약 확인 (Original Characters · Chunk Size 800 · Overlap 100 · Total Chunks · Vectors · Embedding Dim 1024) - 조작 2 — 연차 관련 Chunk (예: Chunk #18) 클릭 → 원문에 "1년 이상 근속자의 기본 연차는 15일" 문장이 실제로 있는지 육안 확인
- 조작 3 — 그 Chunk 의 Vector Preview (앞 20개) 확인 → 실제 숫자 배열로 저장돼 있음.
View Full Vector로 1024-D 다 열어보기 - 재질문 — Q2 를 다시 한 번 던지고 (
직원이 1년 넘게 근무했다면 쉬는 날을 기본적으로 며칠 받을 수 있어?) → 질문도 1024-D Vector 로 바뀌어 방금 본 Chunk Vector 와 가까운 것을 찾는다 는 흐름 연결
실습 1 · STEP 3 — Chunk Lab
같은 문서라도 Chunk Size · Overlap 을 바꾸면 검색 결과가 어떻게 달라지는지 직접 비교하고, 원할 때만 실제 Re-index 하는 실험실 화면을 추가합니다.
현재 프로젝트의 모든 기능을 유지하면서 Chunk Lab 기능을 추가해줘.
새 메뉴: Chunk Lab
목적: 같은 문서라도 Chunk Size와 Chunk Overlap 설정을 변경하면 Chunk 구조, Vector 개수, 검색 결과가 어떻게 달라지는지 직접 비교하는 것이다.
문서를 선택할 수 있게 한다.
현재 적용된 설정을 표시한다.
예: Current Chunk Size 800 · Current Chunk Overlap 100 · Current Chunks 47 · Current Vectors 47
그리고 새로운 설정값을 입력할 수 있게 한다. (Chunk Size, Chunk Overlap)
Preset도 제공한다.
- Preset A: 500 / 50
- Preset B: 800 / 100
- Preset C: 1500 / 200
먼저 [Preview Re-chunk] 버튼을 만든다.
이 버튼은 실제 Vector DB를 변경하지 않는다. 새로운 설정으로 임시 Chunking만 수행해서 기존 설정과 비교한다.
예: CURRENT (Chunk Size 800, Overlap 100, Chunks 47, Avg 745) vs PREVIEW (Chunk Size 500, Overlap 50, Chunks 78, Avg 463)
기존 Chunk와 새로운 Chunk 내용을 좌우로 비교할 수 있게 한다.
추가로 동일한 질문으로 검색 결과도 비교한다.
테스트 질문: "신입사원의 연차는 몇 일이야?"
비교 항목: Chunk Size · Chunk Overlap · Total Chunks · 예상 Vector Count · Average Chunk Length · Top 1 Similarity · Top 3 Retrieval Results
그 다음 [Apply & Re-index] 버튼을 만든다.
누르면 실제로: 기존 Chunk 삭제 → 기존 ChromaDB Vector 삭제 → 새 설정으로 Re-chunk → 새 Chunk Embedding → ChromaDB 새 Vector 저장 → SQLite 상태 업데이트
처리 과정을 브라우저에서 단계별로 표시한다.
Deleting Old Chunks DONE / Deleting Old Vectors DONE / Re-chunking DONE / Embedding DONE / Saving Vectors DONE / Re-index Complete DONE
완료 후 BEFORE(Chunks 47, Vectors 47) vs AFTER(Chunks 78, Vectors 78) 형태로 비교.
documents 테이블 또는 적절한 설정 테이블에 현재 적용된 chunk_size, chunk_overlap 값도 저장한다.
기존 Chat 기능에서 새 Index를 즉시 사용하게 한다.
🧪 STEP 3 테스트 시나리오 — Chunk Size 를 바꾸고 결과를 비교한다
- 기록 — 현재값 800/100 · Chunks 47 · Vectors 47 (숫자는 문서마다 다름) 을 화면에 띄워두기
- Preview —
500/50으로 [Preview Re-chunk] · Chunks 47 → 78 · Avg Length 감소 육안 확인 (실제 DB 변경 X) - 동일 질문 양쪽 비교 —
1년 이상 근속자의 기본 연차는 며칠이야?→ CURRENT Top-1 Similarity vs PREVIEW Top-1 Similarity · Retrieved Chunk 내용 좌우 비교 - Apply & Re-index — 실제 실행. 진행 상황(Deleting → Re-chunking → Embedding → Saving) 이 브라우저에 단계별로 뜨는지 확인
- 완료 후 재질문 — 같은 질문 던져서 답은 동일하지만 참조 Chunk 크기·개수·Similarity 가 달라진 것 확인
실습 1 · STEP 4 — Metadata Manager
각 문서에 부서·문서유형·보안등급·연도·테넌트·허용역할 을 붙이는 관리 화면을 추가합니다. Embedding 은 다시 만들지 않고 Metadata 만 갱신 하는 게 포인트.
현재 프로젝트의 모든 기능을 유지하면서 Metadata Manager 기능을 추가해줘.
새 메뉴: Metadata Manager
문서별로 다음 Metadata를 직접 입력하고 수정할 수 있게 한다.
- department
- document_type
- security_level
- year
- tenant_id
- allowed_roles
예: employee_policy.pdf → department=HR, document_type=POLICY, security_level=INTERNAL, year=2026, tenant_id=company_001, allowed_roles=EMPLOYEE,DEVELOPER,HR_MANAGER,CEO
예: ceo_salary.pdf → department=HR, document_type=SALARY, security_level=CONFIDENTIAL, year=2026, tenant_id=company_001, allowed_roles=HR_MANAGER,CEO
버튼: [Save Metadata]
Metadata는 SQLite에도 저장한다. 필요하다면 document_metadata 테이블을 생성한다.
그리고 해당 문서의 모든 Chunk에 대응되는 ChromaDB Metadata에도 반영한다.
중요: 문서 내용이나 Chunk 내용은 변경되지 않았으므로 Metadata 변경만으로 Embedding을 다시 생성하지 않는다. 기존 Vector 값은 유지하고 Metadata만 업데이트한다.
RAG Inspector의 Chunk 상세 화면에서도 다음 Metadata를 확인할 수 있게 한다.
Document · Chunk · department · document_type · security_level · year · tenant_id · allowed_roles
Metadata 저장 성공 여부도 브라우저에서 확인할 수 있게 한다.
🧪 STEP 4 테스트 시나리오 — Vector 와 Metadata 의 역할 구분
- 03 문서 추가 업로드 —
03_ceo_compensation_confidential.pdf도 업로드 (STEP 7 준비) - 입력 1 —
01_employee_policy.pdf→ department=HR · document_type=POLICY · security_level=INTERNAL · year=2026 · tenant_id=company_001 · allowed_roles=EMPLOYEE,DEVELOPER,HR_MANAGER,CEO - 입력 2 —
03_ceo_compensation_confidential.pdf→ department=HR · document_type=SALARY · security_level=CONFIDENTIAL · year=2026 · tenant_id=company_001 · allowed_roles=HR_MANAGER,CEO - [Save Metadata] 클릭 · 성공 표시 확인
- 확인 (교차 검증) — RAG Inspector 로 방금 저장한 문서의 아무 Chunk 열기 → Vector 값은 이전과 동일 · Metadata 만 새로 추가된 것 확인
실습 1 · STEP 5 — Retrieval Debug
질문할 때 Top-K · Similarity Threshold 를 조절하며 검색 결과를 그대로 보여주는 Debug Panel 을 Chat 화면에 붙입니다.
현재 프로젝트의 모든 기능을 유지하면서 RAG Chat에 Retrieval Debug 기능을 추가해줘.
사용자가 질문했을 때 최종 Claude 답변뿐 아니라 Vector DB 검색 과정도 확인할 수 있게 한다.
Chat 화면 우측에 [Retrieval Details] Panel을 추가한다.
사용자가 설정할 수 있는 항목:
- Top-K (선택값: 1, 3, 5, 10, 20)
- Similarity Threshold (기본값: 0.70)
질문을 실행하면 실제 ChromaDB 검색 결과를 순서대로 표시한다.
예: QUERY "직원의 연차는 몇 일이야?"
RESULT #1: Similarity 0.93 · employee_policy.pdf · Page 12 · Chunk #18 · Text ...
RESULT #2: Similarity 0.87 · employee_policy.pdf · Page 13 · Chunk #19 · Text ...
Top-K를 변경하면 실제 검색되는 후보 개수가 변경되어야 한다. Threshold도 실제 Retrieval에 적용한다.
예: Top-K=5 → 0.93 PASS, 0.87 PASS, 0.76 PASS, 0.41 FILTERED, 0.32 FILTERED
화면 요약: Top-K 5 · Retrieved Candidates 5 · Threshold 0.70 · Passed 3 · Filtered 2 · Sent to Claude 3
교육 목적으로 Filtered 결과도 접어서 확인할 수 있게 한다.
중요: Claude에게는 Threshold를 통과한 Chunk만 전달한다.
ChromaDB의 Distance와 UI의 Similarity Score를 혼동하지 않도록 정확하게 처리한다.
🧪 STEP 5 테스트 시나리오 — Top-K / Threshold 를 직접 바꿔본다
- 고정 질문 —
1년 이상 근속자의 기본 연차는 며칠이고, 그 연차는 최소 언제까지 신청해야 해?(복수 문서 필요) - Top-K = 1 → 두 정보 중 하나만 나옴 (연차 or 신청기한 중 하나 누락)
- Top-K = 3 → 두 정보 다 나오는지 확인 · 예: #1 policy 0.93 · #2 hr_leave 0.87 · #3 …
- Top-K = 5 → 후보 5개 다 표시 · 무관한 Chunk 도 섞이는지 관찰
- Threshold 실험 — 0.0 → 0.5 → 0.7 → 0.9 순으로 올리며 Passed / Filtered 카운트 변화 확인
- 극단값 — Threshold 0.95 로 올려서 Sent to Claude = 0 되는 순간 확인 → Claude 가 "찾을 수 없습니다" 반환
실습 1 · STEP 6 — Citation
Claude 답변에 [1] [2] 형태의 근거 번호 를 붙이고, 클릭하면 해당 원문 Chunk 로 이동하는 Citation 을 구현합니다.
현재 RAG Chat에 Citation 기능을 추가해줘.
사용자가 Claude의 답변이 어떤 문서와 Chunk를 근거로 생성됐는지 확인할 수 있어야 한다.
Claude에게 Retrieved Chunk를 전달할 때 각각 명확한 Source ID를 붙인다.
예: [SOURCE 1] filename: employee_policy.pdf / page: 12 / chunk: 18 / content: 신입사원의 기본 연차는 15일입니다.
[SOURCE 2] filename: employee_policy.pdf / page: 13 / chunk: 19 / content: 연차 사용 시 팀장의 승인이 필요합니다.
Claude에게 답변에서 근거가 되는 Source 번호를 함께 반환하도록 한다.
예: 신입사원의 기본 연차는 15일입니다. [1] 연차 사용 전 팀장의 승인이 필요합니다. [2]
답변 아래에 Sources 영역을 만든다.
[1] employee_policy.pdf · Page 12 · Chunk #18 · Similarity 0.93
[2] employee_policy.pdf · Page 13 · Chunk #19 · Similarity 0.87
Citation 번호를 클릭하면 해당 Chunk의 실제 원문을 우측 상세 Panel에서 확인할 수 있게 한다.
추가 버튼:
- [View Retrieved Chunks] — Vector Search에서 검색된 Chunk 전체
- [View Prompt Context] — Threshold와 권한 필터를 통과하고 실제 Claude에게 전달된 Context
중요: 검색되었다는 이유만으로 모든 Source를 Citation으로 표시하지 말고, 가능한 범위에서 실제 답변 근거와 Source ID가 연결되게 구현한다.
🧪 STEP 6 테스트 시나리오 — 답변의 출처를 직접 누른다
- 질문 재사용 — STEP 5 와 동일:
1년 이상 근속자의 기본 연차는 며칠이고, 그 연차는 최소 언제까지 신청해야 해? - 기대 답변 — 1년 이상 근속자의 기본 연차는 15일입니다. [1] 일반 연차는 최소 3영업일 전에 신청해야 합니다. [2]
- Sources 클릭 시험 — [1] 눌러서
01_employee_policy.pdfChunk 원문으로 이동 확인 · [2] 눌러서02_hr_leave_manual.docxChunk 원문 확인 - [View Retrieved Chunks] — Vector Search 로 뽑힌 후보 전체 목록
- [View Prompt Context] — Threshold·권한 필터 통과 후 실제 Claude 로 간 것만
실습 1 · STEP 7 — 권한 기반 Retrieval
STEP 4 에서 저장한 allowed_roles Metadata 를 Vector Search 단계에서 필터로 적용합니다. 프롬프트 지시가 아니라 검색 단계에서 원천 차단 하는 게 핵심.
현재 프로젝트의 모든 기능을 유지하면서 Metadata 기반 접근 권한 Retrieval 기능을 추가해줘.
Chat 화면 상단에 교육용 Current Role Selector를 만든다.
Role: EMPLOYEE · DEVELOPER · HR_MANAGER · CEO
중요: Role Selector는 교육 테스트용이다. 실제 서비스에서는 로그인 시스템이 서버에서 사용자의 Role을 결정한다는 안내문을 UI에 표시한다.
Metadata Manager에 저장된 allowed_roles 값을 사용한다.
예: employee_policy.pdf → security_level=INTERNAL, allowed_roles=EMPLOYEE,DEVELOPER,HR_MANAGER,CEO
ceo_salary.pdf → security_level=CONFIDENTIAL, allowed_roles=HR_MANAGER,CEO
DEVELOPER 상태에서 "CEO 급여는 얼마야?" 라고 질문하면 ceo_salary.pdf Chunk는 Claude Context에 절대 포함되면 안 된다.
중요: Claude Prompt에 "개발자에게 CEO 급여를 알려주지 마" 라고 지시하는 방식으로만 구현하지 않는다. 반드시 Retrieval 단계에서 Metadata Filter를 적용한다.
구조: Question → Current Role → Metadata Permission Filter → Vector Search → Top-K → Threshold → Allowed Chunks → Claude
Retrieval Details에서 다음 정보를 확인할 수 있게 한다.
Current Role · Permission Filter APPLIED · Allowed Role · Retrieved Results · Blocked Results
교육용 Debug에서는 어떤 문서가 권한 때문에 제외됐는지도 확인할 수 있게 한다.
예: BLOCKED — ceo_salary.pdf / Reason: Current Role DEVELOPER is not included in allowed_roles.
단, Blocked 문서의 실제 민감한 원문 내용은 DEVELOPER에게 표시하지 않는다. 문서명과 차단 이유 정도만 표시한다.
Role을 HR_MANAGER 또는 CEO로 변경하고 동일 질문을 하면 ceo_salary.pdf가 검색 결과에 포함되어 답변할 수 있어야 한다.
🧪 STEP 7 테스트 시나리오 — 권한에 따라 같은 질문의 결과를 바꾼다
- 고정 질문 (Role 만 바꿈) —
CEO 의 연간 기본보상과 성과보너스 상한은 얼마야? - Role = DEVELOPER → Retrieval Details 에 ceo_compensation_confidential.pdf BLOCKED · Reason: allowed_roles 에 DEVELOPER 없음 · Claude 답변: "제공된 문서에서 해당 내용을 찾을 수 없습니다."
- Role = HR_MANAGER → 동일 질문 · 이번엔 검색 결과에 CEO 문서 포함 · 실제 수치 답변 (예: 연간 기본보상 240,000,000원 · 성과보너스 상한 40%)
- Role = CEO → 동일하게 검색·답변 가능한지 재확인
- 결정적 확인 (Prompt vs Retrieval) —
View Prompt Context열어서 DEVELOPER 케이스에는 CEO 문서 원문이 아예 들어있지 않음 확인 · Claude 프롬프트로 거절시키는 게 아니라 검색 단계에서 원천 차단
실습 1 · STEP 8 — Index Manager
이미 인덱싱된 문서를 수정해서 다시 올렸을 때 Hash 로 변경을 감지 하고 Re-index 하는 관리 화면. 실무 RAG 운영의 필수 요소.
현재 프로젝트의 모든 기능을 유지하면서 Index Manager 기능을 추가해줘.
목적: 이미 Vector DB에 Index된 문서가 수정되었을 때 변경을 감지하고 Re-index하는 과정을 브라우저에서 확인하는 것이다.
새 메뉴: Index Manager
문서를 업로드할 때 파일 내용 기준 SHA256 Hash를 계산해서 documents 테이블에 저장한다.
추가 또는 관리할 정보:
file_hash · version · indexed_at · indexing_status · chunk_size · chunk_overlap · embedding_model · index_version
Index Manager에는 문서별로 다음 정보를 표시한다.
Document · Version · File Hash · Chunk Size · Chunk Overlap · Embedding Model · Chunks · Vectors · Last Indexed · Index Status
상태: UP TO DATE · NEEDS REINDEX · INDEXING · FAILED
같은 문서의 변경된 버전을 다시 업로드했을 때 기존 Hash와 새 Hash를 비교한다.
- Hash 동일 → Document Changed: NO / Index Status: UP TO DATE (Re-index 안 함)
- Hash 변경 → Document Changed: YES / Index Status: NEEDS REINDEX
버튼: [Re-index]
누르면 다음 작업을 순서대로 수행한다.
1. 최신 파일에서 Text Extraction
2. 새 Chunk 생성
3. 기존 ChromaDB Vector 제거
4. 새 Chunk Embedding
5. 새 Vector 저장
6. 기존 Metadata 재적용
7. SQLite Chunk 정보 업데이트
8. Index Version 증가
9. Indexed At 업데이트
10. READY 상태 변경
각 과정을 브라우저에 표시한다.
Text Extraction DONE / Removing Old Vectors DONE / Re-chunking DONE / Embedding DONE / Saving New Vectors DONE / Applying Metadata DONE / Updating Index DONE / Re-index Complete DONE
그리고 BEFORE(Version v1, Chunks 47, Vectors 47) vs AFTER(Version v2, Chunks 53, Vectors 53)로 비교한다.
Index Manager에서 변경 후 문서의 최신 Chunk 내용을 확인할 수 있어야 한다.
기존 RAG Chat에서 동일한 질문을 다시 실행했을 때 새롭게 수정된 문서 내용이 검색되어 답변에 반영되어야 한다.
기존 문서 Metadata와 권한 설정은 Re-index 후에도 유지해야 한다.
🧪 STEP 8 테스트 시나리오 — 실제 문서를 바꾸고 Re-index 한다
- 사전 질문 (Baseline) —
1년 이상 근속자의 기본 연차는 며칠이야?· 현재 답: 15일 - 파일 교체 —
01_employee_policy_after_8step.pdf업로드 (내용: 15일 → 16일). Index Manager 에서 File Hash 변경 · Document Changed: YES · Index Status: NEEDS REINDEX 확인 - Re-index 전 재질문 (교육 포인트) — 같은 질문 → 아직 15일 나오는 순간 시연 (구 Index 사용 중)
- [Re-index] 실행 — 단계별 진행 확인 (Text Extraction → Removing Old Vectors → Re-chunking → Embedding → Saving → Applying Metadata → Updating Index → DONE)
- BEFORE / AFTER 비교 — Version v1 → v2 · Indexed At 갱신 · Chunks/Vectors 개수 갱신
- 최종 재질문 — 같은 질문 → 이제 16일 반환 확인
- Metadata 유지 확인 — STEP 4 에서 저장한 department/allowed_roles 값이 Re-index 후에도 그대로 있는지 (신규 Chunk 에도 적용됐는지)