PEP 819 – JSON 패키지 메타데이터
- Author:
- Emma Harper Smith <emma at python.org>
- PEP-Delegate:
- Paul Moore
- Discussions-To:
- Discourse thread
- Status:
- Draft
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 18-Dec-2025
- Post-History:
- 06-Jan-2026
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP에서는 Python 패키지에 JSON으로 인코딩된 코어 메타데이터 및 휠 파일 형식 메타데이터 파일을 도입할 것을 제안합니다. 파이썬 패키지 메타데이터(“핵심 메타데이터”)는 패키지에 관한 정보를 인코딩하기 위해 PEP 241에서 이메일 헤더 RFC 822를 사용하도록 처음 정의되었습니다. 2001년에는 이것이 합리적이었습니다. 이메일 메시지는 표준 라이브러리에 파서가 있는, 널리 사용되는 유일한 표준화 텍스트 형식이었기 때문입니다. 그러나 서로 다른 인코딩의 처리 방식, 줄 바꿈 처리 방식의 차이 및 구현 간의 기타 차이로 인해 수많은 패키징 버그가 발생했습니다. 메타데이터 파일을 인코딩하는 데 JSON 형식을 사용하면 이러한 잠재적인 문제를 광범위하게 제거할 수 있습니다.
동기
이메일 메시지 형식에는 복잡성과 제한 사항이 여러 가지 있어 패키징 메타데이터를 위한 이식 가능한 텍스트 교환 형식으로서의 유용성이 감소합니다. 유효한 코어 메타데이터를 올바르게 생성하려면 email 파서의 구성을 변경해야 하므로, 많은 프로젝트에서는 email 모듈을 사용하지 않고 대신 사용자 지정 방식으로 코어 메타데이터를 생성합니다. 이러한 사용자 지정 생성기에서 이메일 헤더를 생성할 때 마주칠 수 있는 함정이 많습니다. 첫째, 코어 메타데이터 필드의 값에는 줄 바꿈이 포함될 수 있습니다. 이러한 줄 바꿈은 RFC 822에 따라 여러 줄을 적절히 “unfolded” 처리해야 합니다. 특히 인코딩하기 어려운 필드 중 하나는 줄 바꿈과 들여쓰기를 포함할 수 있는 Description 필드입니다. 이메일 헤더에서 이 필드를 인코딩하려면 CRLF 줄 바꿈 뒤에 7개의 공백과 파이프(‘|’) 문자가 와야 합니다. 이제 Description은 메시지 본문에 인코딩할 수 있지만, Author 및 Maintainer 필드에서도 유사한 이스케이프 문제가 발생합니다. 줄 바꿈을 잘못 이스케이프하면 코어 메타데이터가 누락되거나, 불완전하거나, 유효하지 않게 될 수 있습니다. 둘째로, core metadata specifications에서 논의된 바와 같이:
휠 및 설치된 프로젝트의 메타데이터를 포함한 표준 메타데이터 파일 형식은 이메일 헤더 형식을 기반으로 합니다. 그러나 이메일 형식은 여러 차례 개정되었으며, 패키징 메타데이터에 정확히 어떤 이메일 RFC가 적용되는지는 명시되어 있지 않습니다. 정확한 정의가 없는 상황에서 실질적인 표준은 표준 라이브러리의email.parser모듈이email.policy.compat32정책을 사용하여 구문 분석할 수 있는 형식으로 정해집니다.
특정 이메일 RFC가 선택되지 않았으므로 현재 코어 메타데이터 사양에서는 주어진 코어 메타데이터 문서가 유효한지 모호합니다. RFC 822는 PEP에서 명시적으로 나열된 유일한 이메일 표준입니다. 그러나 코어 메타데이터 사양에서는 파일에 기록할 때 코어 메타데이터를 UTF-8을 사용하여 인코딩하도록 요구하기도 합니다. 이로 인해 사실상 코어 메타데이터는 이메일 헤더의 국제화를 규정하는 RFC 6532를 따르게 됩니다. 이는 실질적인 상호 운용성 문제를 일으킵니다. 몇 년 전까지만 해도 코어 메타데이터에서 ASCII가 아닌 이메일을 올바르게 인코딩하는 방법이 명시되지 않아 구문 분석이 모호했습니다. 셋째, 현재 형식은 올바르게 검증하고 구문 분석하기 어렵습니다. 많은 도구는 email 파서의 출력에 문제가 있는지 확인하지 않습니다. 문서 형식이 잘못되었더라도 email 모듈을 통해 유효한 이메일 메시지로 오류 없이 구문 분석될 수 있습니다. 또한 이메일 형식의 제한으로 인해 Project-Url과 같은 필드는 중첩된 키-값 항목의 사용자 지정 인코딩을 만들어야 하므로 구문 분석과 검증이 더욱 복잡해집니다. 마지막으로 스키마가 없기 때문에 이메일 메시지로 인코딩된 메타데이터의 내용을 검증하기 어렵습니다. 현재 형식에 대한 사양을 도입하는 방안은 이전에 논의되었지만, 진전이 없었으며 제기된 문제에 대한 해결책으로 JSON으로 변환하는 방안이 제안되었습니다.
WHEEL 파일 형식은 현재 사용자 지정 키-값 형식으로 인코딩되어 있습니다. 이 형식은 구문 분석하고 작성하기 쉽지만, 내용이 유효한지 확인하려면 수동으로 구문 분석하고 검증해야 합니다. JSON으로 인코딩된 형식으로 전환하면 내용을 더 쉽게 구문 분석하고 검증할 수 있으며, 배포 메타데이터에 일관된 형식을 사용하여 패키징 도구와 서비스를 간소화할 수 있습니다.
근거
잘 명세된 형식의 새로운 핵심 메타데이터 파일을 도입하면 메타데이터를 생성하고 구문 분석하며 검증하는 작업이 크게 쉬워집니다. JSON은 패키지 핵심 메타데이터를 저장하기 위한 자연스러운 선택입니다. JSON은 기계가 쉽게 읽고 쓸 수 있으며 사람이 이해할 수 있고, 여러 언어에서 잘 지원됩니다. 또한 PEP 566은 이미 이메일 형식의 핵심 메타데이터를 JSON으로 정규화하는 방법을 명세하고 있습니다. JSON은 웹에서 데이터 교환을 위해 자주 사용되는 형식이기도 합니다. 고려된 다른 형식에 대한 논의는 거부된 아이디어 섹션을 참조하십시오.
하위 호환성을 유지하려면 JSON 메타데이터 파일을 기존 이메일 형식의 메타데이터 파일과 함께 반드시 생성해야 합니다. 이를 통해 새 형식을 지원하지 않는 도구도 새 패키지의 패키지 메타데이터를 계속 읽을 수 있습니다.
JSON 형식의 메타데이터 파일은 이메일로 인코딩된 파일과 의미상 동등해야 합니다. 이를 통해 두 형식 간의 메타데이터가 모호하지 않게 되며, 두 파일이 모두 존재할 때 도구가 어느 쪽이든 읽을 수 있습니다. 성능을 유지하기 위해 설치 프로그램이 이러한 동등성을 검증할 필요는 없지만, 다른 도구는 검증할 수 있습니다. 일부 도구는 구성 플래그에 따라 검사를 수행하도록 선택할 수 있습니다.
패키지 색인은 패키지가 색인에 추가될 때 메타데이터 파일이 의미상 동등한지 확인해야 합니다. 이는 비용이 낮은 일회성 검사로, 색인 사용자가 유효한 패키지를 제공받도록 보장합니다.
명세
JSON 형식 핵심 메타데이터 파일
Python 배포 패키지의 메타데이터 파일로 새 선택 사항이지만 권장되는 파일인 METADATA.json을 도입합니다. 생성되는 경우 METADATA.json 파일은 현재 이메일 형식의 METADATA 또는 PKG-INFO 파일과 동일한 디렉터리에 배치해야 합니다.
휠의 경우 이는 METADATA.json이 .dist-info 디렉터리에 있어야 함을 의미합니다.
존재하는 경우 METADATA.json 파일은 소스 배포 패키지에서 프로젝트 소스의 루트 디렉터리에 있어야 합니다. JSON 형식의 메타데이터 파일을 선호하는 도구는 파일을 읽기 전에 소스 배포 패키지에 METADATA.json 파일이 존재한다고 가정해서는 안 됩니다.
METADATA.json이 존재하는 경우 METADATA 파일과 METADATA.json 파일의 의미적 내용은 동등해야 합니다. 설치 프로그램은 이 정보를 검증할 수 있습니다. 공개 패키지 색인은 파일이 의미상 동등한지 검증해야 합니다.
새로운 METADATA.json 파일은 배포 메타데이터에 존재하는 경우 installed project metadata에 포함되어야 합니다.
METADATA를 JSON 인코딩으로 변환
핵심 메타데이터의 현재 이메일 형식에서 JSON으로 변환하는 작업은 PEP 566에 설명된 절차를 따라야 하며, 다음과 같이 수정합니다. Project-URL 항목은 원래 이메일 값의 레이블을 키로 포함하고 URL을 값으로 포함하는 객체로 변환해야 합니다. 따라서 전체 절차는 다음과 같습니다.
- 원래의 키-값 형식은
email.parser.HeaderParser를 사용하여 읽어야 합니다; - 변환된 모든 키는 소문자로 변환해야 합니다. 하이픈은 밑줄로 대체하되, 그 외의 모든 문자는 그대로 유지해야 합니다.
- “(Multiple-use”)로 표시된 모든 필드의 변환된 값은 해당 키의 모든 원래 값을 포함하는 단일 리스트여야 합니다.
Keywords필드는 원래 값을 쉼표로 분할하여 리스트로 변환해야 합니다.Project-URL필드는 원래 이메일 값의 레이블을 키로, URL을 값으로 포함하는 JSON 객체로 변환해야 합니다.- 메시지 본문이 있으면
description키의 값으로 설정해야 합니다. - 결과는 문자열 키 딕셔너리로 저장해야 합니다.
위 변환의 한 가지 예외적인 경우는 Project-URL 레이블이 “최대 길이가 32자인 자유 텍스트”라는 점입니다. 이로 인해 레이블을 디코딩하려 할 때 문제가 발생합니다. 따라서 이 PEP에서는 Project-URL 레이블이 쉼표(,) 문자를 제외한 모든 텍스트여야 한다는 요구 사항을 설정합니다. 이를 통해 텍스트를 가장 왼쪽의 쉼표(,) 문자에서 분할하여 Project-URL 항목을 모호하지 않게 구문 분석할 수 있습니다.
코어 메타데이터용 JSON 스키마
JSON으로 인코딩된 코어 메타데이터의 검증을 가능하게 하기 위해 코어 메타데이터용 JSON 스키마가 생성되었습니다. 이 스키마는 코어 메타데이터 사양이 개정될 때마다 업데이트됩니다. 이 스키마는 부록: 핵심 메타데이터용 JSON 스키마에서 사용할 수 있습니다.
Simple Repository API에서 METADATA.json 제공
PEP 658에서는 Simple Repository API에서 패키지 메타데이터를 제공하는 방법을 도입했습니다. 다음과 같이 Simple Repository API를 수정하면 패키지 메타데이터의 JSON 인코딩 버전도 제공할 수 있습니다.
Simple API의 앵커 태그에 새 속성 data-dist-info-metadata-json을 추가할 수 있습니다. 이 속성의 값에는 METADATA.json 파일의 해시 정보가 data-dist-info-metadata와 동일한 형식으로 포함되어야 합니다. data-dist-info-metadata-json이 있으면 저장소는 배포 패키지 경로에 .metadata.json을 덧붙인 위치에서 JSON으로 인코딩된 메타데이터 파일을 제공해야 합니다. 예를 들어 배포 패키지가 /simple/foo-1.0-py3-none-any.whl에서 제공되는 경우, JSON으로 인코딩된 코어 메타데이터 파일은 /simple/foo-1.0-py3-none-any.whl.metadata.json에서 제공되어야 합니다.
JSON 형식 휠 메타데이터 파일
WHEEL 파일의 JSON 인코딩 버전인 새 선택 사항이지만 권장되는 파일 WHEEL.json을 도입해야 합니다. 생성되는 경우 WHEEL.json 파일은 현재 키-값 형식의 WHEEL 파일과 동일한 디렉터리, 즉 .dist-info 디렉터리에 배치해야 합니다. WHEEL 파일과 WHEEL.json 파일의 의미상 내용은 동등해야 합니다. WHEEL.json 도입을 반영하기 위해 휠 파일 형식 버전은 1.1로 증가합니다.
두 파일이 모두 있으면 WHEEL.json 파일을 WHEEL 파일보다 우선하여 사용해야 합니다.
WHEEL의 JSON 인코딩으로 변환
휠 파일 형식 메타데이터의 현재 키-값 형식을 JSON으로 변환할 때는 다음과 같이 진행해야 합니다.
- 원래의 키-값 형식을 읽어야 합니다.
- 변환된 모든 키는 소문자로 변환해야 합니다. 하이픈은 밑줄로 대체하되, 그 외의 모든 문자는 그대로 유지해야 합니다.
Tag필드의 항목은 원래 값들을 포함하는 리스트로 변환해야 합니다.- 결과는 문자열을 키로 하는 딕셔너리로 저장해야 합니다.
이는 METADATA를 JSON 인코딩으로 변환하는 것과 유사한 과정을 따릅니다.
휠 메타데이터용 JSON 스키마
JSON으로 인코딩된 휠 파일 형식 메타데이터를 검증할 수 있도록 휠 메타데이터용 JSON 스키마가 생성되었습니다. 이 스키마는 휠 메타데이터 사양이 개정될 때마다 업데이트됩니다. 이 스키마는 부록: 휠 메타데이터용 JSON 스키마에서 사용할 수 있습니다.
METADATA, PKG-INFO, WHEEL 파일의 사용 중단
이제 METADATA, PKG-INFO, WHEEL 파일은 사용이 중단되었습니다. 이는 향후 PEP에서 METADATA, PKG-INFO, WHEEL 파일을 선택 사항으로 만들고 METADATA.json 및 WHEEL.json 파일이 존재하도록 요구할 수 있다는 의미입니다. 이 변경 사항의 하위 호환성 관련 주의 사항은 다음 절에서 자세히 확인하십시오.
METADATA 및 PKG-INFO 파일의 사용이 중단되더라도, 새로운 핵심 메타데이터 개정판은 JSON과 이메일 모두에 구현하여 의미상 동등성을 유지할 수 있도록 해야 합니다. 마찬가지로 새로운 WHEEL 메타데이터 키는 JSON 형식과 키-값 형식 모두에 구현하여 의미상 동등성을 유지할 수 있도록 해야 합니다.
하위 호환성
METADATA.json 및 WHEEL.json 사양은 새로운 형식이 완전한 하위 호환성을 갖도록 설계되었습니다. 기존 도구는 기존 이메일 형식 파일에서 메타데이터를 읽을 수 있으며, 새로운 도구는 새로운 형식을 활용할 수 있습니다.
향후 휠 사양의 주요 개정판에서는 METADATA, PKG-INFO, WHEEL 파일을 선택 사항으로 만들고 METADATA.json 및 WHEEL.json 파일을 필수로 만들 수 있습니다.
METADATA, PKG-INFO 또는 WHEEL 파일만 포함하는 이전 패키지의 메타데이터를 구문 분석하려면 도구가 이메일 메타데이터와 키-값 형식의 WHEEL 파일에 대한 구문 분석을 무기한 유지해야 한다는 점에 유의하십시오.
보안 관련 사항
JSON으로 인코딩된 핵심 메타데이터의 한 공격 벡터는 JSON 페이로드가 서비스 거부(DoS) 공격에서 과도한 메모리 또는 CPU 리소스를 사용하도록 설계되는 경우입니다. 리소스를 많이 사용하는 대화형 작업을 취소할 수 있는 사용자에게는 이 공격이 영향을 미칠 가능성이 낮지만, 패키지 색인에는 문제가 될 수 있습니다.
이를 방지하기 위해 적용할 수 있는 완화책은 여러 가지가 있습니다.
- JSON 페이로드의 길이를 적절한 크기로 제한할 수 있습니다.
- 리더는
JSONDecoder를 사용하여int및float값의 구문 분석을 생략함으로써 2차 시간 복잡도를 갖는 숫자 구문 분석 공격을 방지할 수 있습니다. - Python 3.15+에서
JSONDecoder에 변경 사항을 기여할 계획이며, 이를 통해 JSON 페이로드의 중첩 깊이를 적절한 수준으로 제한하도록 구성할 수 있게 될 것입니다. 현재 핵심 메타데이터의 최대 깊이는 매핑 및 리스트 필드를 인코딩하기 위한 2입니다.
이러한 완화책을 적용하면 JSON으로 인코딩된 핵심 메타데이터를 이용한 서비스 거부 공격에 대한 우려는 최소화됩니다.
참조 구현
JSON 핵심 메타데이터용 JSON 스키마의 참조 구현은 부록: 핵심 메타데이터용 JSON 스키마에서 사용할 수 있습니다.
또한 packaging 라이브러리의 참조 구현은 여기에서 사용할 수 있습니다.
METADATA.json과 WHEEL.json을 모두 생성하는 참조 구현은 uv 빌드 백엔드에서 여기에서도 사용할 수 있습니다.
거부된 아이디어
다른 파일 형식 사용(TOML, YAML 등)
새 핵심 메타데이터 파일 형식에 TOML이나 다른 형식을 사용할 수도 있지만, JSON은 몇 가지 이유로 선택되었습니다.
- 핵심 메타데이터는 주로 상호 운용하려는 도구와 서비스에서 사용할 기계 간 교환 형식으로 사용됩니다. 따라서 이 선택에서 TOML의 가독성은 중요한 고려 사항이 아닙니다.
- JSON 파서는 여러 언어의 표준 라이브러리에 구현되어 있으며,
json모듈은 아주 오랫동안 Python 표준 라이브러리의 일부였습니다. - JSON은 빠르게 구문 분석하고 생성할 수 있습니다.
- JSON 스키마는 JSON 네이티브이며 널리 사용됩니다.
미해결 문제
JSON 스키마는 어디에서 제공되어야 합니까?
표준 JSON 스키마는 어디에서 제공되어야 합니까? 가능한 선택지로는 packaging.python.org, pypi.org, python.org 또는 pypa.org가 있습니다.
제가 가장 먼저 선택할 곳은 packaging.python.org이지만, 다른 선택지도 고려할 수 있습니다.
감사의 말
uv 빌드 백엔드에서 이 PEP의 참조 구현을 구현하고 사양에 대한 귀중한 피드백을 제공해 주신 Konstantin Schütze에게 감사드립니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.