AI 해결 노트 · 2026-09-18 · 실측 2026-09-18

PDF 용량 줄이기 — 사진 많은 문서는 40분의 1, 글자 문서는 거의 안 줄어듭니다

한 줄로

37.5MB짜리 사진 문서와 74KB짜리 글자 문서를 놓고 용량을 줄여 봤습니다. 사진 문서는 그림을 다시 저장하는 것만으로 3.7MB(10.0%)까지, 해상도를 반으로 낮추면 0.9MB(2.5%)까지 내려갔습니다. 글자 문서는 시험한 방법 가운데 가장 잘 줄인 것이 95.4%였고, 옵션 하나(clean=True)만 켜면 오히려 182%로 커졌습니다. 외부 프로그램은 하나도 깔지 않았습니다.

이런 분께

실측 환경

항목
OSWindows 11 Home 25H2 (10.0.26200.9457)
PowerShell 7 / Git Bash
엣지153.0.4234.32
Python3.12.10
파이썬 꾸러미PyMuPDF 1.28.0, Pillow, NumPy
외부 프로그램깔지 않았습니다 (Ghostscript 등 없음)
시험 파일시험용으로 만든 더미 PDF 두 개. 사진은 프로그램으로 그려 낸 무늬입니다

시험에 쓴 문서 두 개

용량 이야기는 문서가 어떤 것이냐에 따라 답이 완전히 갈립니다. 그래서 두 가지를 만들었습니다.

문서쪽 수크기안에 든 것
① 사진이 많은 문서639,305,252바이트 (37.5MB)그림 12장, 글자 72자
② 글자 위주 문서1274,157바이트 (0.07MB)그림 0장, 글자 13,359자
시험에 쓴 두 문서. 위는 쪽마다 사진 두 장, 아래는 글자만
시험에 쓴 두 문서. 위는 쪽마다 사진 두 장, 아래는 글자만

사진 문서의 1쪽 첫 그림은 1500x1000픽셀 PNG입니다. 쪽에 놓인 자리가 가로 495pt(약 17.5cm)이니 218dpi로 들어가 있는 셈입니다. 그림 한 장이 3,816,210바이트를 차지합니다.

잰 것은 셋입니다. 파일 크기, 글자를 여전히 뽑을 수 있는지, 그리고 확대했을 때 얼마나 뭉개지는지. 마지막 것은 결과 파일과 원본 파일의 1쪽을 각각 200dpi로 그린 뒤 픽셀 값(0~255)의 절대 차이를 평균 낸 값입니다. 아래 표에서 「화질 차이」라고 쓴 것이 이 값이고, 0이면 원본을 그린 것과 같습니다.

크기를 MB로 적은 곳은 1MB를 1,048,576바이트로 셈한 값입니다. 정확한 값은 바이트 쪽을 보시면 됩니다.

먼저 알아 둘 것 — 저장 옵션만으로는 안 줄어듭니다

PyMuPDF의 save에 있는 정리 옵션을 하나씩, 그리고 겹쳐서 걸어 봤습니다. 이름만 보면 garbage는 쓸모없어진 덩어리 치우기, deflate는 압축, clean은 내부 구조 정리입니다.

import fitz

d = fitz.open(r"C:\경로\원본.pdf")
d.save(r"C:\경로\결과.pdf", garbage=4, deflate=True, clean=True)
d.close()

사진 문서(39,305,252바이트)에 걸어 본 결과입니다.

저장 방법결과 크기원본 대비
garbage=439,305,252바이트100.0%
deflate=True39,305,252바이트100.0%
clean=True39,306,909바이트100.0%
garbage=4, deflate=True, clean=True39,304,874바이트100.0%
위에 deflate_images=True 추가39,304,874바이트100.0%
위에 use_objstms=1 추가39,301,917바이트100.0%
ez_save()39,301,959바이트100.0%

가장 많이 줄인 것이 3,335바이트, 0.01%입니다. 모두 0.1~0.2초에 끝났습니다. 어느 경우에도 그림은 12개 그대로, 첫 그림도 1500x1000픽셀 그대로였고 화질 차이는 전부 0.00이었습니다. 이 문서에서 무게를 지고 있는 것이 그림인데, 시험한 저장 옵션은 그림을 그대로 둡니다.

사진이 많은 문서 — 그림을 다시 저장하면 됩니다

PyMuPDF에 그림만 골라 다시 저장하는 rewrite_images가 있습니다. 이름대로라면 dpi_threshold는 손댈 그림을 고르는 기준, dpi_target은 낮출 목표, quality는 JPEG 품질입니다. 실제로 몇 픽셀이 나왔는지는 아래 표에 그대로 적었습니다.

import fitz

d = fitz.open(r"C:\경로\원본.pdf")
d.rewrite_images(dpi_threshold=101, dpi_target=96, quality=70)
d.save(r"C:\경로\결과.pdf", garbage=4, deflate=True, clean=True)
d.close()
설정결과 크기원본 대비그림 크기쪽 위 해상도화질 차이
손대기 전39,305,252바이트100.0%1500x1000 PNG218dpi0.00
threshold 151 / target 150 / q 803,915,066바이트10.0%1500x1000 JPEG218dpi1.83
threshold 151 / target 110 / q 753,325,472바이트8.5%1500x1000 JPEG218dpi1.91
threshold 101 / target 96 / q 70964,328바이트2.5%750x500 JPEG109dpi2.50
threshold 101 / target 72 / q 60836,249바이트2.1%750x500 JPEG109dpi2.70

걸린 시간은 네 번 모두 2초 안쪽이었습니다(로그에 0.6~1.5초).

가장 크게 줄여 준 것은 해상도가 아니라 그림 형식이었습니다. 1500x1000 픽셀 그대로인데도 PNG가 JPEG로 바뀌면서 그림 한 장이 3,816,210바이트에서 364,280바이트로 내려갔습니다. 파일 전체로는 10분의 1입니다. 여기서 해상도까지 반으로 낮추면 2.5%까지 갑니다.

픽셀 수가 1500에서 750으로 딱 절반이 된 것이 눈에 띕니다. target을 110으로 주든 150으로 주든 1500 그대로였고, threshold 101 / target 96으로 내리자 한 번에 750이 됐습니다. 적어 준 dpi에 그대로 맞춰 주지는 않았습니다. 어느 설정에서 몇 픽셀이 되는지는 결과를 뜯어 보고 정하시는 편이 확실합니다.

확대해서 화질을 봤습니다. 같은 자리를 400%로 늘린 것입니다.

사진 문서 1쪽의 같은 자리를 400%로 확대한 네 장. 오른쪽으로 갈수록 뭉개진다
사진 문서 1쪽의 같은 자리를 400%로 확대한 네 장. 오른쪽으로 갈수록 뭉개진다

원본과 target=150, quality=80은 원 테두리가 매끈합니다. target=96부터 테두리에 계단이 보이고 무늬가 뭉개지기 시작하며, target=72는 더 흐립니다. 도면이나 작은 글씨가 찍힌 사진이라면 96 앞에서 멈추시는 편이 안전합니다.

뽑히는 글자는 어느 설정에서도 72자 그대로였습니다.

사진이 많은 PDF 6쪽의 방법별 파일 크기 막대 그림
사진이 많은 PDF 6쪽의 방법별 파일 크기 막대 그림

글자 위주 문서 — 줄일 것이 거의 없습니다

같은 옵션을 12쪽짜리 글자 문서(74,157바이트)에 걸었습니다. 이 표에서 가장 잘 줄인 ez_save()는 이렇게 부릅니다.

import fitz

d = fitz.open(r"C:\경로\원본.pdf")
d.ez_save(r"C:\경로\결과.pdf")
d.close()
저장 방법결과 크기원본 대비
garbage=474,156바이트100.0%
deflate=True74,157바이트100.0%
clean=True135,202바이트182.3%
garbage=4, deflate=True, clean=True77,034바이트103.9%
위에 use_objstms=1 추가73,549바이트99.2%
ez_save()70,712바이트95.4%
subset_fonts()garbage=4, deflate, clean77,033바이트103.9%
rewrite_images(threshold=97, target=96, quality=70)77,139바이트104.0%

가장 잘 줄인 ez_save()가 4.6% 감소입니다. 그리고 clean=True만 켜면 파일이 135,202바이트, 곧 1.8배가 됩니다. 압축하려고 켰다가 오히려 키우는 자리입니다. 왜 커지는지까지는 뜯어보지 않았습니다. garbage=4, deflate=True를 같이 준 경우는 77,034바이트로, 적어도 1.8배까지 가지는 않았습니다.

그림이 없는 문서에 rewrite_images를 걸어도 소용이 없습니다. 104.0%, 곧 줄이는 대신 조금 늘었습니다. 글자 13,359자는 어느 경우에도 그대로 뽑혔습니다.

이 74,157바이트 안에 무엇이 들었는지 세어 봤습니다. 압축된 덩어리(스트림)가 15개인데, 그중 가장 큰 두 개가 글자와 유니코드를 잇는 대응표(50,346바이트)와 한글 글꼴(15,619바이트)입니다. 둘을 더하면 65,965바이트, 파일의 89.0%입니다. 나머지 13개를 다 더해도 1,290바이트이고, 그 안의 글 내용 덩어리에는 이미 FlateDecode가 걸려 있습니다. 글꼴을 빼면 글자가 안 보이니 줄일 거리가 없습니다. 쪽 빼내기 글에서 쪽을 빼도 크기가 안 줄던 것도 같은 덩어리 때문으로 보입니다.

프로그램을 안 깔고 줄이는 길 — 엣지 인쇄

파이썬이 없어도 되는 방법이 하나 있습니다. 사진 문서를 엣지에서 열고 Ctrl+P, 프린터를 「Microsoft Print to PDF」로 골라 인쇄하면 새 PDF가 만들어집니다.

항목원본rewrite_images (150/q80)엣지 인쇄
크기39,305,252바이트3,915,066바이트 (10.0%)1,641,339바이트 (4.2%)
쪽 수666
그림1500x1000 PNG 218dpi1500x1000 JPEG 218dpi1500x1000 JPEG 218dpi
뽑히는 글자72자72자0자
화질 차이0.001.833.38
쪽 크기595.0000 x 842.0000pt595.0000 x 842.0000pt595.3200 x 841.9200pt

이 세 파일 중에서는 엣지 인쇄본이 가장 작습니다. 대신 뽑히는 글자가 0자가 됩니다. 여섯 쪽 모두 글자 0자, 그림 2개, 선·면 그림 8개였습니다. 사진 대장처럼 원래 글자가 거의 없는 문서라면 쓸 만하고, 본문이 있는 보고서라면 잃는 것이 큽니다. 다만 해상도를 낮춘 target=96 쪽(964,328바이트)이 더 작으니, 파이썬을 쓸 수 있다면 굳이 이 길로 가실 것은 없습니다.

얼마나 줄었나 — 한눈에

문서방법줄어든 비율
사진 6쪽저장 옵션만37.5MB37.5MB0.01%
사진 6쪽그림을 JPEG로 (q80, 해상도 유지)37.5MB3.7MB90.0%
사진 6쪽그림을 JPEG로 + 해상도 절반 (q70)37.5MB0.9MB97.5%
사진 6쪽엣지 인쇄37.5MB1.6MB95.8% (뽑히는 글자 0자)
글자 12쪽ez_save()74,157바이트70,712바이트4.6%
글자 12쪽clean=True74,157바이트135,202바이트82.3% 늘어남

정리하면 이렇습니다. 이번 시험에서 사진 문서는 크게 줄었고, 글자 문서는 가장 잘 줄여야 4.6%였습니다. 손에 든 파일이 어느 쪽에 가까운지는 열어서 사진이 있는지 보시면 대충 갈립니다. 글자뿐인 문서인데 용량이 문제라면 쪽을 덜어 내거나 파일을 나누는 쪽을 먼저 보시는 편이 빠릅니다.

실패한 것

>>> d.rewrite_images(dpi_threshold=96, dpi_target=96, quality=70)
ValueError: {dpi_target=} must be less than {dpi_threshold=}

dpi_targetdpi_threshold보다 작아야 한다는 뜻입니다. 이 글의 표는 threshold를 target보다 높게 잡아 다시 돌린 결과입니다(151/150, 151/110, 101/96, 101/72).

확인하지 않은 것

함께 보기