【실전】PDF 무손실 압축: PyMuPDF 기반 구조 최적화 방안
【실전】PDF 무손실 압축: PyMuPDF 기반 구조 최적화 방안
일상 업무에서 우리는 종종 PDF 파일의 크기가 너무 큰 문제에 직면합니다: 이메일 첨부 파일 크기 제한으로 전송할 수 없거나, 업로드 및 다운로드 속도가 느리며, 많은 저장 공간을 차지합니다. 전통적인 압축 방식은 이미지 품질을 저하시켜 흐릿하게 만들거나, 텍스트를 이미지로 변환하여 검색 가능성을 잃게 하여 실질적으로 손해를 보게 됩니다.
오늘은 여러분에게 무손실 PDF 압축 방안을 공유하겠습니다 — PyMuPDF(fitz) 라이브러리를 기반으로 PDF 내부 구조를 최적화하고 중복 데이터를 정리하여 파일 크기를 효과적으로 줄이면서 텍스트 검색 가능성과 시각적 선명도를 완벽하게 유지할 수 있습니다.
1. 핵심 구현 원리
먼저 핵심 코드를 소개합니다. 이는 PDF 구조 최적화 압축을 구현하는 핵심 논리입니다:
import os
from pathlib import Path
import fitz # PyMuPDF
def compress_pdf_simple(input_path, output_path=None):
"""
간단한 PDF 압축 방법 - 구조 최적화만 수행 (무손실)
매개변수:
input_path (str): 입력 PDF 파일 경로
output_path (str): 출력 PDF 파일 경로
반환:
str: 출력 파일 경로
"""
try:
# PDF 파일 열기
doc = fitz.open(input_path)
# 출력 경로 자동 생성 (지정하지 않은 경우)
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
# 핵심: 매개변수 조합을 통해 무손실 압축 구현
doc.save(
output_path,
garbage=4, # 최대한 사용하지 않는 객체 정리
deflate=True, # deflate 무손실 압축 알고리즘 사용
clean=True, # PDF 내부 구조 정리/최적화
pretty=False # 압축된 출력, 공백 문자 제거
)
# 문서 닫기 및 자원 해제
doc.close()
# 압축 정보 계산
original_size = os.path.getsize(input_path)
compressed_size = os.path.getsize(output_path)
compression_ratio = (1 - compressed_size / original_size) * 100
# 압축 결과 출력
print(f"✅ 간단 압축 완료!")
print(f"📄 원본 파일: {input_path} ({original_size / 1024 / 1024:.2f} MB)")
print(f"📦 압축 파일: {output_path} ({compressed_size / 1024 / 1024:.2f} MB)")
print(f"📉 압축률: {compression_ratio:.1f}%")
print(f"🔍 텍스트 검색 가능성 유지: 예")
return output_path
except Exception as e:
print(f"❌ 압축 과정에서 오류 발생: {str(e)}")
return None
# 호출 예시
# compress_pdf_simple("당신의 파일.pdf")
이 방안의 핵심은 PyMuPDF의 save() 메서드의 4개 핵심 매개변수를 활용하여 조합 최적화를 통해 PDF의 "슬림화"를 구현하며, 문서 내용 자체는 전혀 수정하지 않습니다.
2. 핵심 매개변수 심층 분석
2.1 garbage=4: "고아" 객체 정밀 정리
PDF 파일 내부에는 많은 간접 객체(페이지, 글꼴, 이미지, 주석 등)가 존재하며, 문서를 편집할 때 내용을 삭제해도 하위 참조가 즉시 정리되지 않아 많은 "고아 객체"가 쌓이게 됩니다.
| garbage 매개변수 값 | 정리 정도 | 적합한 상황 |
|---|---|---|
| 0 | 정리하지 않음 | 빠른 저장만 필요, 압축 불필요 |
| 1 | 명백히 사용하지 않는 객체 정리 | 경미한 최적화, 호환성 우선 |
| 2 | 참조 관계 심층 검사 | 일반 최적화, 효과와 안전성 균형 |
| 3 | 공격적 정리 | 간단한 PDF 파일 최대 압축 |
| 4 | 최대한 정리 | 여러 번 편집된 문서, 완전성 검증 필요 |
작용 흐름: 모든 간접 객체 탐색 → 참조 관계 그래프 구축 → 참조 없는 객체 삭제 → 저장 공간 해제. 실제 효과: 여러 번 편집된 문서는 10-30%의 크기 감소를 기대할 수 있습니다.
2.2 deflate=True: 일반 무손실 압축 알고리즘
deflate는 PDF 규격에서 추천하는 무손실 압축 알고리즘(기반 LZ77 + 허프만 인코딩)으로, 호환성이 뛰어나 거의 모든 PDF 리더가 디코딩할 수 있습니다.
활성화되면 다음 객체들이 압축됩니다:
- 페이지 내용 흐름
- 글꼴 데이터 흐름
- 다른 알고리즘으로 압축되지 않은 이미지 데이터 흐름
2.3 clean=True: 문서 구조 최적화
PDF는 "문서 구조"와 "내용 흐름" 두 부분으로 구성되어 있으며, clean=True는 구조 부분을 최적화합니다:
- 중복 PDF 객체 제거
- 동일 내용의 객체 참조 병합
- 페이지 트리 구조 최적화
- 메타데이터 중복 정보 정리
실제 효과: 다중 페이지 문서는 5-15%의 크기 감소를 기대할 수 있습니다.
2.4 pretty=False: 압축된 출력
PDF는 본질적으로 이진 형식이며, pretty=True는 가독성을 높이기 위해 들여쓰기, 줄 바꿈 등의 공백 문자를 유지하고, pretty=False는 모든 불필요한 공백 문자를 제거하여 크기를 더욱 줄입니다(이미 deflate 압축된 파일에 보조 효과가 있지만 미미합니다).
3. 전체 압축 프로세스

4. 기술적 난점 및 해결 방안
4.1 압축률 vs 문서 완전성
도전 과제: 공격적인 가비지 수집(garbage=4)은 복잡한 PDF(스크립트/양식 포함)를 손상시킬 수 있습니다. 해결 방안:
- 압축 전에 문서 완전성 검증
- 암호화된 PDF는 먼저 해독한 후 압축
- try-except로 예외를 포착하여 프로그램 충돌 방지
4.2 텍스트 검색 가능성 유지
도전 과제: 일부 압축 방안은 텍스트를 이미지로 변환하여 선택/검색이 불가능하게 만듭니다. 본 방안의 장점:
- 텍스트 내용과 인코딩을 수정하지 않음
- 객체 참조 관계만 최적화
- 글꼴 객체의 완전성 유지
- 검증 방법: 압축 후 PDF 리더로 텍스트 선택 기능 테스트
4.3 대용량 파일 메모리 관리
도전 과제: 수백 MB의 PDF는 메모리 오버플로우를 유발할 수 있습니다. 최적화 제안:
- 대용량 파일을 페이지 단위로 처리
- doc 객체를 즉시 닫아 자원 해제
- 메모리 사용 모니터링 및 스트리밍 처리 채택
4.4 자동 출력 경로 생성
pathlib 라이브러리를 활용하여 경로를 자동 생성하고 원본 파일명 + 압축 태그를 유지하여 크로스 플랫폼 호환성을 보장합니다:
if output_path is None:
input_file = Path(input_path)
output_path = str(input_file.parent / f"{input_file.stem}_simple_compressed{input_file.suffix}")
5. 사용 시나리오 및 효과 예측
5.1 적합한 시나리오
- 학술 문서: arXiv에서 다운로드한 PDF는 일반적으로 많은 중복 정보를 포함합니다.
- 전자책 아카이브: 압축 후 저장 공간 절약
- 문서 전송: 이메일/클라우드 업로드 전 사전 처리
- 배치 처리: Celery와 결합하여 자동화 압축 구현
5.2 효과 예측
| 문서 유형 | 전형적인 압축률 | 비고 |
|---|---|---|
| 순수 텍스트 문서 | 10-25% | 효과가 가장 뚜렷 |
| 이미지가 많은 문서 | 5-15% | 구조 최적화만으로 |
| 여러 번 편집된 문서 | 20-40% | 가비지 수집 효과 뚜렷 |
| 스캔 PDF | 0-5% | 이미지 형식으로 최적화 한계 |
5.3 주의 사항
- 원본 파일 백업: 압축은 비가역적
- 내용 완전성 검증: 압축 후 전면 검사
- 인쇄 효과 테스트: 출력에 영향 미치지 않도록
- 대량 처리 시 분산 아키텍처 사용 권장
6. 유사 방안 비교
| 압축 방안 | 압축률 | 품질 손실 | 텍스트 검색 가능성 | 구현 복잡도 |
|---|---|---|---|---|
| PyMuPDF 구조 최적화 | 10-30% | 없음 | 유지 | 낮음 |
| 이미지 품질 저하 압축 | 30-70% | 명백함 | 유지 | 중간 |
| PDF 재인코딩 | 20-50% | 손실 가능성 | 손실 가능성 | 높음 |
7. 성능 최적화 제안
- 배치 처리: 다중 프로세스를 사용하여 여러 파일을 동시에 처리하여 효율성 향상
- 진행 모니터링: 진행 상황 콜백 함수를 추가하여 사용자 경험 향상
- 증분 압축: PDF 내 변경된 페이지만 압축하여 중복 작업 감소
- 캐시 메커니즘: 이미 압축된 파일 기록하여 중복 처리 방지
8. 요약
핵심 포인트 회고
- 본 방안은 PyMuPDF의
garbage=4,deflate=True,clean=True,pretty=False네 가지 핵심 매개변수를 기반으로 무손실 PDF 압축을 구현합니다; - 방안의 장점은 문서 품질을 손상시키지 않고 텍스트 검색 가능성을 유지하며, 구현이 간단하고 호환성이 좋습니다;
- 다양한 유형의 PDF 압축 효과는 차이가 크며, 스캔 문서의 최적화는 한계가 있고, 여러 번 편집된 순수 텍스트 문서의 효과가 가장 뛰어납니다.
이 PDF 무손실 압축 방안은 실용성과 안전성을 모두 고려하여 코드가 간단하고 통합이 용이하여 대부분의 문서 처리 시나리오에 적합합니다. 더 높은 압축률이 필요하다면 이미지 무손실 압축(예: DPI 최적화)과 결합할 수 있지만 효과와 복잡성의 균형을 주의해야 합니다.
