ZIP으로 파일을 압축해도 실제로는 압축되지 않는 이유

답답한 상황

겪어본 적 있을 것입니다. 동료가 50MB짜리 PDF 보고서를 보냅니다. 이메일로 보내기엔 너무 크다고 생각해 7-Zip에 넣고, 압축을 '최고'로 올린 뒤 기다립니다. 결과는? 49MB짜리 아카이브. 어쨌든 보내고, 받는 쪽이 풀면 파일은 여전히 50MB — 단 1바이트도 줄지 않았습니다.

이건 우연이 아닙니다. 이미 압축된 MP4, JPG, PDF를 가져다 ZIP 파일에 넣으면 크기는 거의 움직이지 않습니다. 하지만 같은 7-Zip을 날것의 TXT, BMP, CSV 파일 폴더에 돌리면 아카이브가 원래 크기의 10분의 1로 줄 수 있습니다.

왜 이런 극적인 차이가 날까요? 답은 대부분의 사람이 배우지 못하는 구분에 있습니다. 아카이브 압축콘텐츠 압축은 근본적으로 다른 작업입니다. 그 차이를 이해하면 줄어들기를 거부하는 파일을 ZIP으로 압축하느라 시간을 낭비하는 일을 멈추게 됩니다 — 그리고 상황에 맞는 올바른 도구를 선택하기 시작합니다.

아카이브 압축: 컨테이너의 기술

아카이브 압축은 컨테이너 수준에서 동작합니다. 두 가지 일을 합니다. 여러 파일을 하나의 컨테이너로 묶는 것, 그리고 바이트 스트림의 통계적 중복을 제거하기 위해 무손실 압축 알고리즘을 적용하는 것입니다.

친숙한 아카이브 형식 — ZIP, 7Z, TAR.GZ, RAR — 은 모두 내부적으로 비슷한 알고리즘에 의존합니다. ZIP은 기본적으로 DEFLATE를 사용하며, 이는 LZ77과 허프만 부호화를 결합한 것입니다. LZ77은 반복되는 바이트 시퀀스를 찾아 거리와 길이 참조로 바꿉니다. 허프만 부호화는 더 자주 나오는 문자에는 더 짧은 이진 코드를, 더 드문 문자에는 더 긴 코드를 할당합니다. 7-Zip의 7Z 형식은 기본적으로 LZMA를 사용하며, 이는 LZ77을 범위 부호화로 확장하고 훨씬 더 큰 사전 창을 지원해 일반적으로 DEFLATE보다 더 나은 압축률을 달성합니다.

여기서 핵심은 이것입니다. 아카이브 압축은 파일 내용을 결코 수정하지 않습니다. 각 파일을 불투명한 바이트 스트림으로 취급하고 그 스트림 안의 통계적 패턴을 사냥합니다. ZIP 아카이브를 풀면 파일은 원본과 바이트 단위로 완전히 동일하게 돌아옵니다 — 단 하나의 픽셀도 바뀌지 않습니다.

이것이 도입부의 시나리오를 설명합니다. PDF는 이미 내부적으로 DEFLATE로 이미지와 폰트 스트림을 압축했습니다. JPG 자체가 압축 형식입니다. MP4는 비디오 프레임을 압축하는 데 H.264나 H.265를 사용합니다. 이 파일들은 이미 중복이 짜여져 나왔으므로 아카이브 알고리즘이 다룰 것이 거의 남지 않습니다. 반대로 BMP 비트맵, 무압축 WAV 오디오, 일반 텍스트 CSV 파일은 압축 가능한 반복으로 가득 차 있습니다 — 그곳이 바로 아카이브 압축이 빛나는 곳입니다.

아카이브 압축이 진정으로 뛰어난 점은 여러 파일 간의 중복을 제거하는 것입니다. 어떤 폴더에 같은 로고 워터마크와 비슷한 도구 모음을 가진 스크린샷 100장이 있다고 가정해 봅시다. LZMA의 큰 사전은 이러한 파일 간 반복을 식별해 각 파일을 개별적으로 압축하는 것보다 훨씬 더 나은 압축을 달성할 수 있습니다. 이것이 파일들을 하나의 아카이브로 묶는 것이 하나씩 압축하는 것보다 더 효율적인 이유입니다.

여기서 압축 사전의 역할을 이해할 가치가 있습니다. DEFLATE와 LZMA 모두 최근에 본 데이터의 슬라이딩 창 — 사전 — 을 유지하고 새 바이트를 그것과 대조합니다. DEFLATE의 창은 32KB로 고정되어 반복을 얼마나 먼 곳에서 찾을 수 있는지를 제한합니다. LZMA는 64MB 이상의 사전을 설정할 수 있어, 배치의 첫 파일에 나타난 패턴이 마지막 파일에 다시 나타날 때도 여전히 참조할 수 있음을 뜻합니다. 이것이 비슷한 파일이 많은 하나의 큰 아카이브가 많은 작은 아카이브보다 훨씬 더 잘 압축되는 이유입니다. 사전이 활용할 재료가 더 많고 파일 간 중복이 포착됩니다. 각 파일을 따로 묶으면 모든 아카이브가 빈 사전으로 시작해 파일 간 중복이 완전히 사라집니다.

콘텐츠 압축: 내부에서 재구축

콘텐츠 압축은 다른 길을 택합니다. 파일이 몇 개인지 신경 쓰지 않고 아무것도 묶지 않습니다. 대신 단일 파일의 내부 구조로 들어가 그 파일의 특정 유형에 따라 데이터를 최적화합니다.

기법은 파일 유형에 따라 완전히 달라집니다.

이미지는 리샘플링(4000×3000 원본을 1920×1080으로 축소), 재인코딩(PNG를 WebP나 AVIF로 변환), 색 심도 축소(24비트를 8비트 인덱스로)가 가능합니다. 8MB짜리 폰 사진은 합리적인 해상도와 품질 조정만으로 눈에 보이는 차이 없이 500KB 미만으로 일상적으로 압축됩니다.

PDF는 내장 이미지를 다운샘플링하고, 무압축 폰트 스트림을 서브셋 CFF로 변환하고, 참조되지 않은 객체를 제거하고, 중복 XObjects를 병합할 수 있습니다. 고해상도 일러스트가 가득한 50MB짜리 디자인 문서는 콘텐츠 압축 후 5~8MB로 줄어드는 경우가 흔합니다.

PDF는 본질적으로 컨테이너 자체이기에 특히 가르침이 되는 예입니다. PDF는 각 이미지를 스트림 객체로, 각 폰트를 또 다른 스트림으로, 텍스트를 인코딩된 콘텐츠 스트림으로 저장합니다. 대부분의 생성기는 이미 텍스트와 폰트 스트림에 DEFLATE를, 사진 이미지에 JPEG이나 DCT를 적용합니다. 그래서 아카이브 도구에 넣은 PDF는 거의 줄지 않습니다 — 따기 쉬운 과일은 이미 없습니다. 대신 콘텐츠 압축은 모든 스트림을 재검토합니다. 대상 디스플레이에 필요한 해상도를 초과하는 이미지를 다운샘플링하고, 허용되는 곳에서는 무손실 이미지 스트림을 JPEG로 변환하며, 내장 썸네일과 숨겨진 레이어 같은 메타데이터를 버리고, 중복된 폼 XObjects를 평탄화합니다. 결과는 같은 데이터를 감싸는 더 얇은 껍데기가 아니라 근본적으로 더 가벼운 문서입니다.

폰트는 서브셋화할 수 있어, 수만 자의 문자가 든 폰트 파일 전체를 배포하는 대신 문서에서 실제로 쓰이는 수십 개의 글리프만 남길 수 있습니다.

비디오와 오디오는 더 효율적인 코덱으로 재인코딩할 수 있습니다 — 예컨대 H.264를 H.265로 올리면 동등한 품질에서 비트레이트가 대략 절반으로 줄어듭니다.

콘텐츠 압축에는 결정적 특성이 있습니다. 파일의 내부 데이터를 수정하며, 흔히 손실 압축입니다. 압축된 이미지는 원래 픽셀로 복원할 수 없고, 서브셋화된 폰트는 완전한 서체로 다시 조립할 수 없습니다. 그 대가로 파일이 원천에서 더 작아집니다 — 풀 필요 없이 그대로 쓸 수 있는 상태가 됩니다.

시각적 비교

아래 다이어그램은 두 접근 방식 간의 워크플로 근본적 차이를 보여줍니다.

Archive compression vs content compression difference flowchart: 7-Zip packaging path vs content-level compression path

왼쪽 경로는 파일 내용이 결코 변하지 않는 '묶기–전송–풀기–복원' 사이클입니다. 오른쪽 경로는 파일 자체가 재구축되는 단방향 '분석–최적화–생성' 프로세스입니다.

코드 예제: 차이 보기

Python은 그 구분을 아주 선명하게 만듭니다.

zipfile을 이용한 아카이브 압축


import zipfile
import os

# 아카이브 압축: 여러 파일을 하나의 zip으로 묶기
source_files = ['report.pdf', 'photo.jpg', 'data.csv']
archive_name = 'bundle.zip'

with zipfile.ZipFile(archive_name, 'w', zipfile.ZIP_DEFLATED) as zf:
    for file in source_files:
        zf.write(file)

# 결과 측정
original = sum(os.path.getsize(f) for f in source_files)
packed = os.path.getsize(archive_name)
print(f"Original total: {original / 1024 / 1024:.2f} MB")
print(f"Archive size:   {packed / 1024 / 1024:.2f} MB")
print(f"Ratio: {packed / original * 100:.1f}%")

# 전형적인 출력 (이미 압축 형식인 파일들):
# Original total: 58.30 MB
# Archive size:   57.10 MB
# Ratio: 97.9%

비율을 보세요 — 거의 변화가 없습니다. 이 파일들은 이미 압축 형식이므로 아카이브 압축은 무력합니다.

PIL을 이용한 콘텐츠 압축


from PIL import Image
import os

# 콘텐츠 압축: 이미지 데이터 자체를 최적화
src = 'photo.jpg'
dst = 'photo_optimized.jpg'

img = Image.open(src)
before = os.path.getsize(src)

# 세 가지 측면의 콘텐츠 압축
img.thumbnail((1920, 1080))  # 해상도 낮추기
img.save(dst, 'JPEG',
         quality=75,        # 품질 낮추기
         optimize=True,     # 허프만 테이블 최적화
         progressive=True)  # 점진적 인코딩

after = os.path.getsize(dst)
print(f"Original size: {before / 1024 / 1024:.2f} MB")
print(f"Optimized size: {after / 1024:.2f} KB")
print(f"Ratio: {after / before * 100:.1f}%")

# 전형적인 출력:
# Original size: 8.20 MB
# Optimized size: 480.50 KB
# Ratio: 5.7%

같은 '압축'이라는 단어이지만, 하나는 58MB를 57MB로 바꾸고 다른 하나는 8MB를 480KB로 바꿉니다. 그 격차는 각각이 무엇에 손대는지에서 옵니다. 첫째는 컨테이너만 재정렬하고, 둘째는 콘텐츠를 다시 씁니다.

한눈에 보는 비교

항목아카이브 압축콘텐츠 압축
하는 일파일을 묶고 중복을 제거파일의 내부 데이터를 최적화
대상파일 컨테이너(다중 파일 수준)파일 내용(데이터 수준)
방식DEFLATE / LZMA 등 무손실 알고리즘리샘플링 / 트랜스코딩 / 서브셋화
손실 여부무손실. 풀 때 완전히 복원 가능대부분 손실. 되돌릴 수 없음
사용 방법사용 전에 풀어야 함그대로 사용, 풀기 불필요
전형적 시나리오여러 파일 전송, 백업크기 축소, 웹 최적화, 이메일 첨부
효과중복에 의존. 이미 압축된 파일에는 거의 010배 이상의 압축률 달성 가능

사례 연구: 50MB PDF의 두 가지 운명

실제 50MB PDF(고해상도 스캔 이미지 여러 페이지)를 가져와 비교해 봅시다.

접근 A: 아카이브 압축

  • 도구: 7-Zip, LZMA2 최고
  • 결과: 50MB → 49.2MB
  • 이유: PDF의 내부 이미지 스트림은 이미 DCTDecode로 JPEG 압축되어 있고 폰트 스트림은 FlateDecode를 사용합니다. 아카이브 압축은 더 이상 활용할 중복을 찾지 못합니다.

접근 B: 콘텐츠 압축

  • 작업: 내장 이미지를 150 DPI로 다운샘플링, JPEG 품질을 75로 낮춤, 폰트 서브셋화, 참조되지 않은 객체 제거
  • 결과: 50MB → 6.8MB
  • 이유: 압축은 PDF의 대부분 — 고해상도 스캔 — 을 겨냥합니다. 150 DPI면 화면 읽기가 사실상 동일해 보이지만 파일은 7분의 1로 줄어듭니다.

두 '압축'은 7배의 차이를 만들어냅니다. 그 PDF를 이메일로 보내는 것이 목표라면 접근 B가 정답이고, 접근 A는 그저 수고를 낭비할 뿐입니다.

올바른 접근 선택

두 도구를 모두 손에 쥐면 결정은 간단해집니다. 무엇을 이루려 하는지 자문해 보세요.

  • 한 번에 많은 파일을 옮겨야 하나요? 아카이브 압축을 쓰세요. 한 번에 묶고 체크섬을 달며 파일 간 중복을 짜냅니다 — 백업, 소스 코드 배포, 폴더 구조 전송에 이상적입니다.
  • 단일 파일을 더 작게 만들어야 하나요? 콘텐츠 압축을 쓰세요. 이메일용 50MB PDF는 ZIP에서 줄지 않지만, 내부 이미지를 다운샘플링하면 극적으로 줄어듭니다.
  • 둘 다 필요하나요? 먼저 각 파일에 콘텐츠 압축을 적용한 뒤 결과를 아카이브 압축으로 묶으세요. 순서는 타협할 수 없습니다. 콘텐츠 최적화는 파일 내부가 여전히 접근 가능한 동안, 아카이브에 봉인되기 전에 일어나야 합니다.

쓸 만한 정신적 모델이 있습니다. 아카이브 압축은 전송 비용을 낮추고, 콘텐츠 압축은 저장 비용을 낮춥니다. 파일이 전송할 만큼 이미 작지만 서버에 영구히 산다면, 콘텐츠 압축은 매 다운로드마다 절약되는 대역폭에서 이득을 봅니다. 한 번만 파일 묶음을 보낸다면 아카이브 압축이 더 가벼운 선택입니다.

자주 묻는 질문

Q1: 왜 7-Zip은 PDF, JPG, MP4를 거의 줄이지 못하나요?

이 파일들이 이미 압축 형식이기 때문입니다. PDF는 내부적으로 이미지와 폰트 스트림을 DEFLATE로 압축하고, JPG는 이미지 데이터를 DCT 변환으로 압축하며, MP4는 비디오 프레임을 H.264/H.265로 압축합니다. 아카이브 알고리즘은 이미 짜여진 데이터에 직면하므로 제거할 통계적 중복이 남지 않습니다. 아카이브 압축은 날것의 무압축 데이터 — BMP, WAV, 일반 텍스트 — 에 효과적입니다.

Q2: 콘텐츠 압축은 품질을 잃나요? 크기와 품질은 어떻게 맞추나요?

대부분의 콘텐츠 압축은 손실이지만, 손실 정도는 제어 가능합니다. 이미지의 경우 해상도와 품질을 조정해 크기와 선명도를 맞바꿉니다 — 화면용으로는 품질 75에서 72~96 DPI면 보통 충분하고, 인쇄에는 300 DPI가 필요합니다. 폰트 서브셋화는 무손실이며 표시에 영향을 주지 않습니다. 핵심은 획일적 설정을 적용하는 것이 아니라 압축 수준을 사용 사례에 맞추는 것입니다.

Q3: 아카이브 압축과 콘텐츠 압축을 함께 쓸 수 있나요?

네, 그리고 흔히 그렇게 합니다. 전형적 워크플로는 먼저 콘텐츠 압축을 적용해 각 파일을 원천에서 줄인 뒤, 아카이브 압축을 적용해 더 작아진 파일들을 전송용으로 묶는 것입니다. 순서가 중요합니다 — 먼저 콘텐츠, 그다음 아카이브. 순서를 바꾸면 파일 구조가 아카이브 안에 갇혀 콘텐츠 압축이 개입하지 못합니다. 먼저 콘텐츠를 최적화하고 그다음 묶으면 두 가지 이점을 모두 얻습니다.

결론

아카이브 압축과 콘텐츠 압축은 모두 '압축'이라는 이름을 띠고 있지만 서로 다른 층에서 동작합니다. 아카이브 압축은 컨테이너 수준에서 동작해 — 무손실로 묶고 중복을 제거하지만 이미 압축된 파일에는 효과가 제한적입니다. 콘텐츠 압축은 데이터 수준에서 동작해 — 흔히 손실 압축으로 파일 내부를 재구축하지만 원천에서 줄입니다.

다음에 줄어들지 않는 '압축된' 파일을 마주할 때 자문해 보세요. 내가 컨테이너를 압축하고 있는가, 아니면 콘텐츠를? 올바른 층을 선택하면 압축은 마침내 제 역할을 합니다.

관련 글:

파일 압축이 필요하신가요? SmartSlim을 사용해 보세요

자체 개발한 Rust 압축 엔진 기반으로 PDF/이미지/비디오/Office/OFD 등 10대 분류 40+ 포맷을 지원합니다. 로컬 압축으로 데이터가 외부로 나가지 않습니다.