PEP 784 – Zstandard를 표준 라이브러리에 추가하기
- Author:
- Emma Harper Smith <emma at python.org>
- Sponsor:
- Gregory P. Smith <greg at krypto.org>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Created:
- 06-Apr-2025
- Python-Version:
- 3.14
- Post-History:
- 07-Apr-2025
- Resolution:
- 25-Apr-2025
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
Zstandard는 널리 채택되었고 성숙했으며 매우 효율적인 압축 표준입니다. 이 PEP는 기본 구현인 Meta의 zstd 라이브러리를 감싸는 Python 래퍼를 담은 새 모듈을 Python 표준 라이브러리에 추가할 것을 제안합니다. 또한 PyPI의 패키지와 이름이 충돌하는 것을 피하고 Python 사용자에게 통일된 인터페이스를 제공하기 위해, 표준 라이브러리의 압축 모듈은 compression.* 패키지 아래로 옮겨집니다.
동기
CPython에는 zlib (DEFLATE), gzip, bzip2, lzma 등 여러 압축 형식을 위한 모듈이 있으며, 각각 널리 사용되고 있습니다. 널리 쓰이는 압축 알고리즘을 포함하는 것은 폭넓게 유용한 표준과 유틸리티를 통합한다는 Python의 “배터리 포함(batteries included)” 철학에 부합합니다. lzma는 이러한 모듈 중 가장 최근의 것으로, Python 3.3에서 추가되었습니다.
그 이후로 Zstandard는 합리적인 CPU 및 메모리 비용으로 높은 압축률을 달성하는 고성능 압축과 압축 해제 모두에서 선호되는, 현대의 사실상 표준 압축 라이브러리가 되었습니다. Zstandard는 bzip2나 zlib(DEFLATE)보다 훨씬 높은 압축률을 달성하면서도 LZMA보다 상당히 빠르게 압축을 해제합니다.
Zstandard는 컴퓨팅의 다양한 분야에서 널리 채택되었습니다(widespread adoption). 수많은 하드웨어 구현은 Zstandard에 대한 장기적인 투자와 함께, Zstandard가 앞으로도 수년간 사실상 표준 압축 방식으로 남을 것이라는 기대를 보여 줍니다. 이는 RFC 8478에서 이루어진 Zstandard의 IETF 표준화로도 뒷받침됩니다. Zstandard 압축은 ZFS와 Btrfs 파일 시스템 모두에도 구현되어 있습니다.
Zstandard는 매우 효율적인 압축 덕분에 brotli, lzo, ucl 등 다른 현대 압축 형식을 대체했습니다. LZ4는 처리량이 매우 높은 상황에서 여전히 사용되지만, 이러한 상황 중 일부에서는 Zstandard도 사용할 수 있습니다. LZ4를 포함하는 것은 범위를 벗어나지만, 이 PEP가 도입하는 compression 네임스페이스에 앞으로 추가할 만한 매력적인 후보가 될 것입니다.
PyPI에는 Python용 Zstandard 바인딩이 여러 개 있으며, 각각 API가 다르고 zstd 라이브러리를 바인딩하는 방식에 대한 선택도 다릅니다. 표준 라이브러리에 공식 모듈을 도입하는 목적 중 하나는 Zstandard에 대한 간단한 압축/압축 해제 API를 원하는 Python 사용자의 혼란을 줄이는 것입니다. 기존 패키지들은 계속해서 확장된 API를 제공하거나 더 새로운 Zstandard 버전의 기능을 통합할 수 있습니다.
표준 라이브러리에 Zstandard 지원을 추가하는 또 다른 이유는 tarfile 모듈에서 Zstandard를 지원해 달라고 요청하는, 오랫동안 열려 있던 이슈(python/cpython#81276)를 해결하기 위함입니다. 이 이슈는 CPython 트래커에서 열려 있는 이슈 중 “좋아요(thumbs up)”를 다섯 번째로 많이 받았으며, 상당한 논의와 관심을 불러일으켰습니다. 또한 ZIP 형식은 Zstandard compression format ID를 표준으로 정하고 있으므로, zipfile 모듈과 통합하면 Zstandard 압축을 사용하는 ZIP 아카이브를 열 수 있습니다. 이 PEP의 참조 구현에는 zipfile, tarfile, shutil 모듈과의 통합이 포함되어 있습니다.
Zstandard 압축은 Python wheel 패키지를 더 작게 만들고 설치 속도를 크게 높이는 데에도 사용될 수 있습니다. Anaconda는 conda 패키지 형식에 Zstandard를 채택했을 때 상당한 속도 향상을 확인했습니다:
Conda의 다운로드 크기는 약 30~40% 줄었고, 압축 해제는 극적으로 빨라졌습니다. […] 전체적으로 약 2.5배의 속도 향상이 나타났으며, 이는 거의 전적으로 새 파일 형식에 사용된 zstd 압축의 극적으로 빨라진 압축 해제 속도 덕분입니다.
다양한 압축 라이브러리와 형식을 폭넓게 비교하는 벤치마크인 lzbench에 따르면(according to lzbench), Zstandard는 휠의 기존 zlib 기반 압축보다 압축률이 상당히 높습니다. 이 PEP는 wheel 형식이나 다른 패키징 표준에 대한 어떠한 변경도 규정하지 않지만, 표준 라이브러리에 Zstandard 바인딩이 있으면 향후 PEP에서 Python wheel 패키지의 사용자 경험을 개선할 수 있게 됩니다.
근거
compression 패키지 도입
zstd와 zstandard 임포트 이름은 모두 PyPI의 프로젝트들이 이미 선점하고 있습니다. 기존 바인딩 중 어느 쪽의 사용자에게도 문제가 생기지 않도록, 이 PEP는 압축 라이브러리를 위한 새 네임스페이스인 compression을 도입할 것을 제안합니다. 이 이름은 표준 라이브러리에서 사용하도록 PyPI에 이미 예약되어 있습니다. 새 Zstandard 모듈의 이름은 compression.zstd가 됩니다. 다른 압축 모듈들은 새 compression 패키지에서 다시 내보냅니다.
압축 모듈에 공통 네임스페이스를 제공하면 여러 가지 이점이 있습니다. 첫째, 압축 모듈을 어디에서 찾아야 하는지에 대한 사용자의 혼란이 줄어듭니다. 둘째, 최상위 compression 모듈은 hashlib의 algorithms_available과 비슷하게, 어떤 압축 형식을 사용할 수 있는지에 대한 정보를 제공할 수 있습니다. PEP 775가 채택되면, zlib을 나열하는 compression.algorithms_guaranteed도 제공할 수 있습니다. 마지막으로, compression 네임스페이스는 앞으로 다른 압축 형식을 표준 라이브러리에 병합할 때 생길 수 있는 문제를 방지합니다. 새로운 압축 형식은 CPython에 통합되기 전에 PyPI에 먼저 공개될 가능성이 높습니다. 따라서 새로운 압축 형식의 임포트 이름은 해당 모듈을 CPython에 포함하는 것을 검토할 무렵에는 이미 선점되어 있을 가능성이 높습니다. 압축 모듈을 패키지 접두사 아래에 두면 앞으로 발생할 수 있는 이름 충돌 문제를 방지할 수 있습니다.
여러 Python 버전에서 호환성을 유지하려는 코드는 다음 패턴을 사용하여 호환성을 보장할 수 있습니다:
try:
from compression.lzma import LZMAFile
except ImportError:
from lzma import LZMAFile
이렇게 하면 새 임포트 이름을 사용할 수 있을 때는 그 이름을 사용하고, 그렇지 않으면 이전 이름으로 대체합니다.
pyzstd에 기반한 구현
이 PEP의 구현은 pyzstd project를 기반으로 합니다. 이 프로젝트를 선택한 것은 해당 코드가 원래 Ma Lin이 CPython에 업스트림하기 위해 작성한 것이기 때문이며(originally written to be upstreamed), Ma Lin은 오늘날 표준 라이브러리에서 사용되는 output buffer implementation도 작성했습니다. 이후 이 프로젝트는 Rogdham이 넘겨받았으며 PyPI에 공개되어 있습니다. pyzstd의 API는 bz2와 lzma 같은 표준 라이브러리의 다른 압축 모듈 API와 비슷합니다.
지원하는 최소 Zstandard 버전
지원하는 최소 Zstandard 버전으로는 2020년 5월에 출시된 v1.4.5를 선택했습니다. 이 버전은 LTS 릴리스를 포함하여 여러 Linux 배포 패키지 저장소에서 제공되는 Zstandard 버전을 검토한 결과를 바탕으로 최소 버전으로 선택되었습니다. 이 버전 선택은 기존 LTS Linux 배포판과의 호환성을 최대화하기 위해 상당히 보수적으로 이루어졌지만, 새로운 Python 릴리스는 일반적으로 새로운 배포판 릴리스의 일부로 패키징된다는 점을 고려하면 더 새로운 Zstandard 버전을 선택할 수도 있을 것입니다.
명세
compression 네임스페이스
압축 모듈을 위한 compression이라는 이름의 새 네임스페이스를 도입합니다. 이 패키지의 최상위 모듈은 처음에는 비어 있지만, 앞으로 압축 루틴과 상호 작용하기 위한 표준 API가 최상위에 추가될 수 있습니다.
compression.zstd 모듈
표준 라이브러리의 다른 압축 모듈과 일치하는 Zstandard 압축 API를 갖춘 새 모듈 compression.zstd를 도입합니다. 구체적으로는 다음과 같습니다
compress()/decompress()- 한 번에 수행하는 압축 또는 압축 해제를 위한 APIZstdFile/open()- 스트림 및 파일류 객체와 상호 작용하기 위한 APIZstdCompressor/ZstdDecompressor- 점진적 압축 또는 압축 해제를 위한 API
또한 Zstandard 고유의 기능도 일부 포함합니다:
ZstdDict/train_dict()/finalize_dict()- Zstandard 딕셔너리를 다루기 위한 API로, 비슷한 데이터로 이루어진 작은 조각을 많이 압축할 때 유용합니다
libzstd 선택적 의존성
libzstd 라이브러리는 CPython의 선택적 의존성이 됩니다. 이 라이브러리를 사용할 수 없으면 compression.zstd 모듈도 사용할 수 없습니다. Unix 플랫폼에서는 일반적인 빌드 환경 감지 과정의 일부로 이를 자동으로 처리합니다.
Windows에서는 CPython이 Windows에서 의존하는 라이브러리를 빌드하는 데 사용하는 소스 의존성에 libzstd가 추가됩니다.
다른 압축 모듈
Python 3.14에서 새 임포트 이름 compression.lzma, compression.bz2, compression.gzip, compression.zlib이 도입되며, 이들은 각각 기존 lzma, bz2, gzip, zlib 모듈의 내용을 다시 내보냅니다. 앞으로는 compression 서브 모듈이 정식 임포트 이름이 됩니다. 최소 지원 Python 버전 요구 사항상 가능해지면, Python 문서에서는 기존 최상위 모듈 이름보다 새 압축 모듈 이름을 사용하도록 권장할 것입니다.
_compression 모듈은 비공개로 표시되어 있으므로 즉시 compression._common._streams로 이름이 바뀝니다. 이 모듈의 현재 내용이 표준 라이브러리 압축 모듈의 스트림 API(예: LZMAFile)를 위한 I/O 관련 도우미이기 때문에 이 새 이름을 선택했습니다.
하위 호환성
이 PEP는 하위 호환성을 깨는 변경을 도입하지 않습니다. 현재 기존 압축 모듈을 폐지하거나 제거할 계획은 없습니다. 기존 모듈의 폐지나 제거는 향후 결정에 맡기지만, 이 PEP가 수락된 날로부터 최소 5년이 지나기 전에는 이루어지지 않습니다.
보안 영향
모든 새로운 C 코드와 마찬가지로, 특히 신뢰할 수 없을 수도 있는 사용자 입력을 다루는 코드에는 메모리 안전성 문제의 위험이 있습니다. 저자는 _zstd 코드를 퍼징하여 견고함을 확인할 수 있도록 libfuzzer 통합을 기여할 계획입니다. 또한 압축 및 압축 해제 루틴을 검사하는 테스트가 여러 개 있습니다. 이 테스트들은 AddressSanitizer로 컴파일했을 때 오류 없이 통과합니다.
새로운 의존성을 들이는 데에는 항상 보안 위험도 따르지만, zstd 라이브러리는 성숙하고, 커밋마다 퍼징되며, Meta의 버그 바운티 프로그램에 참여하고 있습니다.
교육 방법
새 모듈의 문서는 참조 구현 브랜치에 있습니다. 기존 모듈의 문서도 새 이름을 참조하도록 갱신될 것입니다.
참조 구현
참조 구현에는 _zstd C 코드, compression.zstd 코드, tarfile, shutil, zipfile에 대한 수정 사항, 그리고 추가된 각 새 API와 통합에 대한 테스트가 포함되어 있습니다. 또한 다른 압축 모듈을 다시 내보내는 코드도 포함되어 있습니다.
기각된 아이디어
모듈 이름을 zstdlib으로 짓고 새 compression 네임스페이스를 만들지 않기
새 compression 네임스페이스를 만드는 대신 zstdlib 같은 다른 이름을 임포트 이름으로 정하는 방안도 있습니다. zst, libzstd, zstdcomp 같은 여러 다른 이름도 제안되었습니다. 논의 결과, 이 이름들은 오타를 내기 너무 쉽거나 직관적이지 않은 것으로 판단되었습니다. 게다가 기존 임포트 이름과 겹치는 문제는 앞으로 표준 라이브러리에 추가될 압축 형식에서도 계속될 가능성이 높습니다. 널리 쓰이는 고속 압축 형식인 LZ4에는 PyPI의 패키지인 lz4가 있으며, 그 임포트 이름은 lz4입니다. 압축 형식마다 이 문제를 따로 해결하기보다는, 이미 확보된 compression 네임스페이스를 사용하여 한 번에 완전히 해결하는 것이 더 낫습니다.
Python 3.14에 실험적인 _zstd 패키지 도입
이 PEP는 Python 3.14의 새 기능에 대한 베타 마감 직전에 게시되었기 때문에, 이름은 결정하지 않은 채 패키징 도구가 더 일찍 사용할 수 있도록 패키지를 비공개 모듈 _zstd로 명명하자는 제안이 있었습니다. 이렇게 하면 3.15 개발 기간 동안 최종 모듈 이름을 논의할 시간을 더 확보할 수 있습니다. 그러나 비공개 모듈을 도입하는 방안은 호응을 얻지 못했습니다. 표준 라이브러리의 비공개 모듈을 외부에서 사용하는 것에 대한 기대치와 계약이 불분명합니다.
compression 대신 표준 라이브러리 네임스페이스 도입
compression 네임스페이스의 대안 하나는 표준 라이브러리 전체를 위한 std 네임스페이스를 도입하는 것입니다. 그러나 이는 합의된 의미 체계, 마이그레이션 경로, 패키지 이름이 없는 상태에서 3.14에 넣기에는 너무 큰 변경으로 여겨졌습니다. 게다가 향후 std 네임스페이스를 도입하는 PEP에서 compression 하위 모듈들을 std 네임스페이스로 평탄화하도록 언제든지 정의할 수 있습니다.
compression에 zipfile과 tarfile 포함
압축은 아카이브 도구와 함께 자주 사용되므로, zipfile과 tarfile을 모두 compression 네임스페이스 아래에 두는 방안은 매력적입니다. 그러나 압축은 아카이브 도구 외에도 사용될 수 있습니다. 예를 들어, 네트워크 요청을 gzip으로 압축할 수 있습니다. 게다가 tar 같은 형식은 자체적으로 압축을 포함하지 않고 외부 압축에 의존합니다. 따라서 이 PEP는 zipfile이나 tarfile을 compression 아래로 옮기는 것을 제안하지 않습니다.
compression 아래에 gzip을 포함하지 않음
GZip 형식 RFC는 여러 블록과 그 내용에 대한 메타데이터를 포함할 수 있는 형식을 정의합니다. 이런 점에서 GZip은 ZIP이나 tar 같은 아카이브 형식과 상당히 비슷합니다. 그럼에도 불구하고 실제 사용에서 GZip은 아카이브 형식보다는 압축 형식으로 취급되는 경우가 많습니다. 여러 언어가 GZip을 어떻게 분류하는지 살펴보면, 아카이브 형식이 아닌 압축 형식으로 분류하는 것이 지배적인 추세입니다.
또한 Python의 gzip 모듈은 주로 단일 블록 콘텐츠에 초점을 맞추고 있으며 다른 압축 모듈과 유사한 API를 가지고 있으므로, compression 네임스페이스에 잘 들어맞습니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.