Skip to content

PDF 압축

DocumentEditor::save_with_options()는 한 번의 처리로 스트림 재압축, 고아 객체의 가비지 컬렉션, Fast Web View 선형화를 모두 수행할 수 있습니다. 세 가지를 가장 간단히 적용하는 방법은 이 모두를 하나의 명령으로 감싼 pdf-oxide compress CLI입니다.

바인딩 지원 현황. compress / garbage_collect / linearize를 포함하는 완전한 SaveOptionsRust (editor.save_with_options(path, opts))와 Python (바인딩된 경우 doc.save(..., compress=True, ...))에서 공개되어 있습니다. **Node, WASM, Go, C#**에서는 CLI (pdf-oxide compress input.pdf -o out.pdf)를 서브프로세스나 빌드 단계로 실행하세요 — SaveOptions가 각 FFI 표면에 연결되기 전까지 CLI가 이들 바인딩이 공유하는 안정적인 인터페이스입니다.

CLI (모든 플랫폼)

# 기본: input_compressed.pdf 생성
pdf-oxide compress input.pdf

# 출력 파일 명시
pdf-oxide compress input.pdf -o smaller.pdf

# 크기 비교 출력
pdf-oxide compress report.pdf
# → Compressed report.pdf -> report_compressed.pdf (3412901 -> 1847200 bytes)

CLI는 기본적으로 compress: true, garbage_collect: true, linearize: true를 활성화합니다 — ISO 32000을 준수한 상태에서 가장 작은 파일을 만드는 조합입니다.

Rust API

use pdf_oxide::editor::{DocumentEditor, EditableDocument, SaveOptions};

let mut editor = DocumentEditor::open("input.pdf")?;

editor.save_with_options("output.pdf", SaveOptions {
    compress: true,         // 비압축 스트림 전체에 FlateDecode 적용
    garbage_collect: true,  // 고아 객체 제거
    linearize: true,        // Fast Web View를 위한 선형화
    ..Default::default()
})?;

SaveOptions 필드

필드 기본값 효과
compress CLI에서 true / 기본값 false 비압축 상태로 저장된 스트림에 FlateDecode를 적용
garbage_collect CLI에서 true 트레일러에서 더 이상 참조되지 않는 간접 객체 제거
linearize CLI에서 true Linearized(“Fast Web View”) 레이아웃을 출력해 전체 파일이 내려오기 전에 뷰어가 1페이지를 렌더링
encryption None EncryptionConfig를 붙여 암호화 저장 — 암호화 및 보안 참조

각 옵션이 실제로 하는 일

  • compress — 모든 콘텐츠 스트림, Form XObject, ToUnicode CMap, 메타데이터 스트림을 순회합니다. 필터가 없거나 인식되지 않는 필터가 있는 스트림은 FlateDecode로 다시 감쌉니다. 이미 압축된 스트림(JBIG2 이미지, CCITT 테이블, 기존 Flate)은 그대로 둡니다.
  • garbage_collect/Root/Info를 시작점으로 도달 가능성 스캔을 수행하고, 살아 있는 간접 객체에 표시해서 출력 xref에는 그들만 기록합니다. remove_page, flatten_forms, erase_region 같은 대규모 편집 후 고아 객체가 남았을 때 유용합니다.
  • linearize — 첫 페이지의 콘텐츠 스트림과 리소스 의존성이 파일 앞부분에 오도록 객체를 재정렬하고, 선형화 딕셔너리와 힌트 스트림을 추가합니다. PDF 뷰어는 파일을 순서대로 다운로드하며 전체가 도착하기 전에 1페이지를 렌더링합니다. CDN에서 서비스되는 PDF에서 사용자 체감 이득이 가장 큽니다.

언제 압축할지

  • 대량 편집 후flatten_forms, flatten_all_annotations, apply_all_redactions를 실행했거나 많은 페이지를 삭제한 경우, GC와 재압축으로 파일 크기가 보통 30–60% 줄어듭니다.
  • 배포나 메일 발송 전 — 최종 사용자는 파일 크기를 신경 쓰며, Linearize는 느린 연결에서도 첫 페이지가 즉시 표시되는 체감을 줍니다.
  • ETL 파이프라인의 마지막 단계로 — 추출과 재생성이 끝난 뒤 파이프라인 끝에서 한 번만 압축하세요. 변환마다 압축 해제와 재압축을 반복하지 마세요.

압축하면 안 되는 경우

  • 잦은 증분 편집 중에는 — 전체 재작성은 xref 스트림과 오브젝트 스트림을 잃게 되어 증분 추가를 작게 유지하는 구조가 깨집니다. 대화형 편집 루프에서는 SaveOptions::incremental()을 쓰고 압축은 마지막 패스로 남기세요.
  • 이미 공격적으로 압축된 PDF — 스트림에 이미 좋은 predictor가 적용된 FlateDecode 필터가 있다면 겨우 몇 퍼센트만 줄어들 수 있습니다. 파이프라인에 연결하기 전에 pdf-oxide compress를 한 번 실행해 측정해 보세요.

예상 크기 감소치

실세계 PDF에서 측정한 전형적인 절감(3,830개 파일의 테스트 코퍼스 기준):

소스 이전 이후 절감
스캔된 청구서 (비압축 스트림) 2.4 MB 0.8 MB 약 66%
LaTeX 연구 논문 1.1 MB 0.95 MB 약 14%
정부 양식 (flatten 이후) 890 KB 240 KB 약 73%
이미 최적화된 마케팅 PDF 1.8 MB 1.75 MB 약 3%

대량 편집된 파일과 flatten 처리 이후의 양식에서 가장 큰 효과를 얻습니다. 이미 최적화된 파일은 선형화만으로 작은 절감을 봅니다.

먼저 복호화/인증하기

DocumentEditor는 아직 비밀번호 인증 호출을 제공하지 않으므로 암호화된 PDF는 먼저 복호화해야 합니다. PdfDocument.open_with_password()로 읽고 비암호화 사본을 저장한 뒤, 그 사본을 에디터에서 여세요.

use pdf_oxide::api::Pdf;
use pdf_oxide::editor::{DocumentEditor, EditableDocument, SaveOptions};

let doc = Pdf::open_with_password("protected.pdf", "pw")?;
doc.save("temp-unencrypted.pdf")?;

let mut editor = DocumentEditor::open("temp-unencrypted.pdf")?;
editor.save_with_options("compressed.pdf", SaveOptions {
    compress: true,
    garbage_collect: true,
    linearize: true,
    ..Default::default()
})?;

Python에서도 같은 패턴을 PdfDocument(path, password="pw") + save() + CLI로 적용할 수 있습니다.

관련 페이지