저장된 파일을 검색 가능한 벡터로 바꾼다
박수현 · (사)한국정보공학기술사회 · 2026
add_document(path) 한 함수로🎯 목표: 파일 경로 입력 → 검색 가능 상태를 단일 서비스 함수로 캡슐화한다.

🖼️ 인덱싱 · 업로드(multipart)→저장→Loader→Splitter(1000/100)→OpenAIEmbeddings(1536d)→Chroma.add_documents→영속화
💡 이 5단계가
vectorstore.add_document()의 내부 구현이다. route 는 이를 한 줄로 호출한다.
from langchain_community.document_loaders import (
TextLoader, PyPDFLoader, Docx2txtLoader)
def load_file(path):
ext = os.path.splitext(path)[1].lower()
if ext == ".pdf": return PyPDFLoader(path).load()
if ext == ".docx": return Docx2txtLoader(path).load()
return TextLoader(path, encoding="utf-8").load()
Document 리스트 → 이후 단계는 형식과 무관.docx 분기는 확장 예시 — Docx2txtLoader 추가로 형식 확장📁 참고:
8.web_app/.../services/vectorstore.py
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=100) # 1000자 / 100 겹침
def add_document(path):
docs = load_file(path) # ① 로드
chunks = splitter.split_documents(docs) # ② 분할
for c in chunks: # ③ 메타데이터
c.metadata["source"] = os.path.basename(path)
store.add_documents(chunks) # ④⑤ 임베딩+저장
return {"source": path, "chunks": len(chunks)}
store = 영속 ChromaDB (OpenAIEmbeddings·1536차원으로 자동 임베딩+저장)chunk_overlap=100 = 경계에 걸친 문장 누락을 줄이는 겹침source 메타데이터 = 목록·삭제·출처 추적의 키🔑 route 는
add_document(saved_path)한 줄만 호출한다.
💡 학습·소규모 환경에서는 🅰️ 통합으로 충분하다. 본 코스 데모도 업로드 시 즉시 색인한다.
add_documents 가 임베딩+저장을 한 번에