RAG2026-5일6차시 · 문서 로딩 실습13 / 19← 이전목차다음 →MetaContents

6차시. 문서 로딩 실습

10. 이번 차시 실습 정리

출처: 원본 PDF 06차시_문서로딩실습.pdf 19쪽 · 쪽 그림 19쪽

오늘 만든 코드를 하나로 합쳐봅시다. 다음 차시에서 이 결과를 그대로 이어받습니다.

📝 src/ingest.py — 오늘의 완성본

Python
import os, re
from langchain_community.document_loaders import PyPDFLoader

NOISE = ["㈜한국주식회사 대외비"]

def load_documents(path: str):
    # 문서를 읽고, 정리하고, 검증까지 한 번에
    docs = PyPDFLoader(path).load()

    for d in docs:
        # 잡음 제거
        text = d.page_content
        for n in NOISE:
            text = text.replace(n, "")
        text = re.sub(r"\n{3,}", "\n\n", text)
        d.page_content = text.strip()

        # metadata 보강
        d.metadata["filename"] = os.path.basename(path)
        d.metadata["page_no"] = d.metadata.get("page", 0) + 1

    # 검증
    empty = [d.metadata["page_no"] for d in docs
             if len(d.page_content) < 10]
    if empty:
        print("⚠ 비어 있는 페이지:", empty)
    print(f"✓ {len(docs)}쪽 로딩 완료 "
          f"(총 {sum(len(d.page_content) for d in docs)}자)")

    return docs

if __name__ == "__main__":
    docs = load_documents("data/manual.pdf")
    print(docs[0].page_content[:200])

실행 결과 예시 (코드를 읽고 만든 예상 화면입니다. 실제 실행 결과, 특히 모델의 답은 다를 수 있습니다)

출력
✓ 3쪽 로딩 완료 (총 1529자)
1
제품 사용 설명서
가정용 공기청정기 AP-3300
목차
1. 제품 개요
2. 설치 방법
3. 사용 방법
4. 환불 및 교환 규정
5. 보증 및 무상 A/S
6. 문제 해결(FAQ)
7. 고객센터 안내
8. 제품 사양
9. 품질보증서

💡 이 함수의 좋은 점
읽기 · 정리 · 검증을 한 함수로 묶었습니다.
앞으로 어떤 문서를 다루든
load_documents("파일경로") 한 줄이면
깨끗하게 정리된 Document 목록을 얻습니다.
15차시에서 indexer.py를 만들 때
이 함수를 그대로 가져다 씁니다.

실습 코드 · 06/ingest.py

실습 코드: 실습/src/06/ingest.py · 위의 원본 PDF 6차시 19쪽 「이번 차시 실습 정리」과 이어집니다.

Python
# ============================================================
# 6차시 | PPT: 06차시_문서로딩실습.pptx
# 역할: PDF를 읽고, 잡음 제거와 페이지 검사 후 Document 리스트를 돌려줌
# 입력: ../../data/notice.pdf (직접 실행 시)
# 출력: "N쪽 로딩 완료"와 첫 페이지 본문
# 흐름:
#   PDF 경로
#     -> PyPDFLoader.load()
#     -> 페이지마다 본문 정리, metadata 추가
#     -> 짧은 페이지 검사
#     -> 글자 수 합계 print -> docs 반환
# ============================================================
# Document: 페이지 하나의 본문(page_content)과 metadata 딕셔너리
# metadata: 파일명, 쪽 번호처럼 본문 옆에 붙여 두는 부가 정보

from langchain_community.document_loaders import PyPDFLoader
import os
import re

# 본문에서 지울 문구 목록입니다. 이번 안내문에는 이 단어가 없습니다.
NOISE = ["대외비"]

def load_documents(path):
    loader = PyPDFLoader(path)    
    docs = loader.load()
    for d in docs:
        text = d.page_content

        # 목록에 있는 단어를 빈 문자열로 바꿉니다.
        for noise in NOISE:
            text = text.replace(noise, "")

        # 줄바꿈이 3번 이상 연속이면 2번으로 줄이려는 식입니다.
        # 반환값을 text에 다시 넣지 않으므로, 이 줄은 저장된 본문을 바꾸지 않습니다.
        re.sub(r"\n{3,}", "\n\n", text)

        d.page_content = text.strip()

        # 메타데이터 
        # basename은 경로에서 파일 이름만 꺼내는 함수입니다.
        # 뒤에 ()가 없어서 함수를 호출하지 않고, 함수 자체를 metadata에 넣습니다.
        d.metadata["filename"] = os.path.basename

        # PDF의 page는 0부터입니다. 사람에게 보여줄 쪽 번호는 1을 더합니다.
        d.metadata["page_no"] = d.metadata.get("page", 0) + 1

    # 글자가 거의 없는 페이지 번호를 모읍니다.
    empty_pages = []
    for d in docs:
        text = d.page_content.strip()
        if len(text) < 10:
            page = d.metadata.get("page", "?")
            empty_pages.append(page)
    
    # 짧은 페이지가 있을 때만 안내를 출력합니다.
    if empty_pages:
        print("스캔 pdf 파일의 경우, OCR 처리가 필요합니다. 아래 페이지를 확인하세요.")

    total_len = 0
    for d in docs:
        total_len += len(d.page_content)
    print(f"{len(docs)}쪽 로딩 완료 (총 {total_len} 자)")

    return docs

# 이 파일을 직접 실행할 때만 아래가 실행됩니다. import할 때는 실행되지 않습니다.
if __name__ == "__main__":
    docs = load_documents("../../data/notice.pdf")
    print(docs[0].page_content)

실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)

출력
===== 실행 결과 샘플 =====
실행: cd 실습/src/06
      python ingest.py
1쪽 로딩 완료 (총 209 자)
고객 안내문
1. 환불 규정
상품 수령 후 7 일 이내에 환불을 신청하실 수 있습니다.
단순 변심의 경우 왕복 배송비는 고객 부담입니다.
2. 교환 규정
상품 불량의 경우 30 일 이내에 교환이 가능합니다.
이 경우 배송비는 당사가 부담합니다.
3. 고객센터
운영 시간은 평일 09:00 ~ 18:00 입니다.
전화 1588-0000 / 이메일 help@example.com

코드 해설

PDF를 읽고, 잡음 제거와 페이지 검사 후 Document 리스트를 돌려줌입니다. 입력은 ../../data/notice.pdf (직접 실행 시)이고, 출력은 "N쪽 로딩 완료"와 첫 페이지 본문입니다.

주석에 적힌 흐름입니다.

출력
PDF 경로
-> PyPDFLoader.load()
-> 페이지마다 본문 정리, metadata 추가
-> 짧은 페이지 검사
-> 글자 수 합계 print -> docs 반환

코드 앞에서 고정해 두는 말입니다.

  • Document: 페이지 하나의 본문(page_content)과 metadata 딕셔너리
  • metadata: 파일명, 쪽 번호처럼 본문 옆에 붙여 두는 부가 정보

함수와 클래스로 나누어 읽습니다.

  • load_documents: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

← 이전 절6차시 · 9. 자주 겪는 문제와 해결법다음 절 →6차시 · 체크리스트와 과제