6차시. 문서 로딩 실습
5. 실습 ② — PDF 읽기
출처: 원본 PDF 06차시_문서로딩실습.pdf 10~11쪽 · 쪽 그림 10쪽 11쪽
이제 실전에서 가장 많이 쓰는 PDF입니다. TXT와 결정적으로 다른 점이 하나 있습니다.
📄 PDF는 페이지마다 Document가 하나씩 생깁니다
10페이지짜리 PDF를 읽으면
→ Document 10개가 만들어집니다
각 Document의 metadata에는
→ 몇 페이지인지가 자동으로 기록됩니다
이게 바로 출처 표시가 가능한 이유입니다!
5-1) 코드 작성
📝 src/load_pdf.py
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("data/manual.pdf")
docs = loader.load()
print("총 페이지 수 :", len(docs))
print()
# 모든 쪽을 살펴보기 (지금은 2쪽뿐입니다)
for d in docs:
page = d.metadata["page"]
preview = d.page_content[:60].replace("\n", " ")
print(f"[{page}쪽] {preview} ...")실습 코드 · 06/load_pdf.py
실습 코드: 실습/src/06/load_pdf.py · 위의 원본 PDF 6차시 10쪽 「5-1) 코드 작성」과 이어집니다.
# ============================================================
# 6차시 | PPT: 06차시_문서로딩실습.pptx
# 역할: PDF 로더로 안내문 PDF를 읽고 첫 페이지를 출력
# 입력: ../../data/notice.pdf
# 출력: 페이지 수, 첫 페이지 본문, metadata
# 흐름:
# notice.pdf -> PyPDFLoader.load() -> Document 리스트 -> print
# ============================================================
# Document: 페이지 하나의 본문과 metadata를 담는 객체
# metadata: source(파일 경로), page(0부터 세는 쪽 번호) 등이 들어 있는 딕셔너리
# PDF 전용 로더입니다. pypdf 패키지가 설치되어 있어야 합니다.
from langchain_community.document_loaders import PyPDFLoader
# 경로는 실행 위치(실습/src/06) 기준입니다. 다른 폴더에서 실행하면 FileNotFoundError가 납니다.
loader = PyPDFLoader(
"../../data/notice.pdf"
)
# load()는 쪽마다 Document 하나씩 담은 리스트를 돌려줍니다.
documents = loader.load()
print(f"문서 길이 => {len(documents)}")
print()
# [0]은 첫 쪽입니다. 본문이 비어 있으면 스캔 PDF를 의심합니다.
print(f"문서 내용 =>\n {documents[0].page_content}")
print()
# metadata의 page는 0부터 셉니다. 사람에게 보여 줄 때는 1을 더합니다.
print(f"메타 =>\n {documents[0].metadata}")실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)
===== 실행 결과 샘플 =====
실행: cd 실습/src/06
python load_pdf.py
문서 길이 => 1
문서 내용 =>
고객 안내문
1. 환불 규정
상품 수령 후 7 일 이내에 환불을 신청하실 수 있습니다.
단순 변심의 경우 왕복 배송비는 고객 부담입니다.
2. 교환 규정
상품 불량의 경우 30 일 이내에 교환이 가능합니다.
이 경우 배송비는 당사가 부담합니다.
3. 고객센터
운영 시간은 평일 09:00 ~ 18:00 입니다.
전화 1588-0000 / 이메일 help@example.com
메타 =>
{'producer': 'LibreOffice 24.2', 'creator': 'Writer', 'creationdate': '2026-09-03T06:20:59+00:00', 'author': 'Un-named', 'source': '../../data/notice.pdf', 'total_pages': 1, 'page': 0, 'page_label': '1'}코드 해설
PDF 로더로 안내문 PDF를 읽고 첫 페이지를 출력입니다. 입력은 ../../data/notice.pdf이고, 출력은 페이지 수, 첫 페이지 본문, metadata입니다.
주석에 적힌 흐름입니다.
notice.pdf -> PyPDFLoader.load() -> Document 리스트 -> print코드 앞에서 고정해 두는 말입니다.
- Document: 페이지 하나의 본문과 metadata를 담는 객체
- metadata: source(파일 경로), page(0부터 세는 쪽 번호) 등이 들어 있는 딕셔너리
파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.
실습 코드 · 06/validate.py
실습 코드: 실습/src/06/validate.py · 위의 원본 PDF 6차시 10쪽 「5-1) 코드 작성」과 이어집니다.
# ============================================================
# 6차시 | PPT: 06차시_문서로딩실습.pptx
# 역할: PDF에서 글자가 거의 없는 페이지가 있는지 검사
# 입력: ../../data/notice.pdf 를 읽은 Document 리스트
# 출력: 짧은 페이지가 있을 때만 OCR 안내 문장. 없으면 출력 없음
# 흐름:
# notice.pdf -> PyPDFLoader.load() -> validate(docs)
# -> 10자 미만 페이지를 모음
# -> 있으면 print, 없으면 끝
# ============================================================
# Document: 페이지 하나의 본문(page_content)과 metadata를 담는 객체
# metadata: page 키에 쪽 번호(0부터)가 들어 있습니다.
# OCR: 스캔 이미지 PDF에서 글자를 읽어 내는 처리. 이 파일은 필요 여부만 알립니다.
# PDF 파일을 페이지별 문서로 읽기 위한 로더를 가져옵니다.
from langchain_community.document_loaders import PyPDFLoader
# 실행 위치를 기준으로 PDF 파일의 경로를 지정합니다.
loader = PyPDFLoader(
"../../data/notice.pdf"
)
# PDF의 각 페이지를 문서 객체로 불러옵니다.
docs = loader.load()
def validate(docs):
# 텍스트가 비어 있거나 너무 짧은 페이지 번호를 저장합니다.
empty_pages = []
# 불러온 각 페이지 문서를 차례로 검사합니다.
for d in docs:
# 앞뒤 공백을 제거한 페이지 텍스트를 확인합니다.
text = d.page_content.strip()
# 글자 수가 10자 미만이면 텍스트 추출이 제대로 되지 않았다고 봅니다.
if len(text) < 10:
# 페이지 번호가 없으면 물음표를 기본값으로 사용합니다.
page = d.metadata.get("page", "?")
empty_pages.append(page)
# 텍스트가 거의 없는 페이지가 있으면 OCR이 필요하다는 안내를 출력합니다.
# 짧은 페이지가 없으면 이 분기는 실행되지 않고, 함수는 아무것도 출력하지 않습니다.
if empty_pages:
print("스캔 pdf 파일의 경우, OCR 처리가 필요합니다. 아래 페이지를 확인하세요.")
# 불러온 PDF 페이지들을 검사합니다.
validate(docs)실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)
===== 실행 결과 샘플 =====
실행: cd 실습/src/06
python validate.py
(표준 출력 없음. notice.pdf 본문이 10자 이상이라 empty_pages가 비고 print가 실행되지 않습니다.)코드 해설
PDF에서 글자가 거의 없는 페이지가 있는지 검사입니다. 입력은 ../../data/notice.pdf 를 읽은 Document 리스트이고, 출력은 짧은 페이지가 있을 때만 OCR 안내 문장. 없으면 출력 없음입니다.
주석에 적힌 흐름입니다.
notice.pdf -> PyPDFLoader.load() -> validate(docs)
-> 10자 미만 페이지를 모음
-> 있으면 print, 없으면 끝코드 앞에서 고정해 두는 말입니다.
- Document: 페이지 하나의 본문(page_content)과 metadata를 담는 객체
- metadata: page 키에 쪽 번호(0부터)가 들어 있습니다.
- OCR: 스캔 이미지 PDF에서 글자를 읽어 내는 처리. 이 파일은 필요 여부만 알립니다.
함수와 클래스로 나누어 읽습니다.
validate: 이름 그대로 한 가지 일만 합니다. 본문 주석을 같이 읽습니다.
파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.
5-2) 실행 결과
총 페이지 수 : 2
[0쪽] 제품 사용 설명서 1. 제품 개요 본 제품은 가정용 공기청정기로 최대 10평 공간에 적합하며 ...
[1쪽] 3. 환불 및 교환 규정 상품을 받은 후 7일 이내에는 환불을 신청할 수 있으며 ...⚠️ 페이지 번호는 0부터 시작합니다
metadata의 page 값은 0, 1, 2, ... 순입니다.
사람이 보는 "1페이지"는 코드에서는 page=0 입니다.
나중에 사용자에게 출처를 보여줄 때는
page + 1을 해주는 것이 친절합니다.