PEP 714 – Simple API에서 dist-info-metadata 이름 변경
- Author:
- Donald Stufft <donald at stufft.io>
- PEP-Delegate:
- Paul Moore <p.f.moore at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Accepted
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 06-Jun-2023
- Post-History:
- 06-Jun-2023
- Resolution:
- 27-Jun-2023
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Simple API의 HTML 및 JSON 형식에서 PEP 658이 제공하는 메타데이터의 이름을 변경하고, 클라이언트와 서버가 이름 변경을 처리하는 방법에 대한 지침을 제공합니다.
동기
PEP 658은 클라이언트가 전체 아티팩트를 다운로드하지 않고도 메타데이터를 가져와 사용할 수 있도록, Simple API를 통해 제공되는 아티팩트의 핵심 메타데이터 파일을 호스팅하는 메커니즘을 명시했습니다. 이후 PEP 691은 Simple API에서 HTML 대신 JSON을 사용할 수 있는 기능을 추가하기 위해 작성되었으며, 여기에는 PEP 658메타데이터에 대한 지원도 포함되었습니다.
안타깝게도 PyPI는 아주 최근에야 recently PEP 658을 지원했으며, 이 지원은 PEP 658의 dist-info-metadata키가 JSON 표현에서 잘못 data-dist-info-metadata로 명명되는 bug 와 함께 배포되었습니다. 그러나 해당 버그를 수정하려고 시도하던 중, pip도 또한 bug가 있었으며, JSON 표현에서 dist-info-metadata를 어떤 방식으로든 사용하면 pip가 예외와 함께 치명적으로 실패한다는 사실이 발견되었습니다.
pip의 버그는 적어도 v22.3부터 존재했으며, 이는 해당 버전이 약 8개월 동안 배포되었다는 뜻입니다. 따라서 Python 릴리스, 하위 Linux 릴리스, 컨테이너, 가상 환경 등에 포함되기에 충분히 긴 기간이었습니다.
이로 인해 pip의 버그 때문에 PyPI의 버그를 수정하면 pip가 작동하지 않게 되어 수정할 수 없지만, 해당 pip 버전은 널리 배포되기에 충분히 오래된 상태라는 난처한 상황에 놓였습니다. 설상가상으로, 이러한 방식으로 손상된 pip 버전은 버그를 수정한 후에는 새로운 수정 버전의 pip를 설치하는 것까지 포함하여 PyPI에서 어떤 것도 설치할 수 없습니다.
근거
이러한 버그를 수정하기 위한 앞으로의 방안에는 세 가지 주요 선택지가 있습니다.
- 사양을 변경하지 않고 pip의 버그를 수정한 다음, 일정 기간 기다렸다가 PyPI의 버그를 수정하여 수정되지 않은 pip를 사용하는 사용자가 PyPI에서 새로운 pip조차 설치할 수 없게 만듭니다.
- (1)과 동일하게 수행하되, PyPI를 특수 처리하여 해당 메타데이터를 사용할 수 있더라도 pip에는 PEP 658메타데이터를 제공하지 않도록 합니다. 이렇게 하면 손상된 버전을 사용 중인 사람은 pip를 업그레이드할 수 있지만, 다른 작업은 할 수 없습니다.
- 현재 pip가 처리할 수 없는 키를 피하도록 사양을 변경하여 PyPI가 해당 키를 제공하고, 새로운 pip 버전이 출시되어 해당 키를 활용할 수 있도록 합니다.
이 PEP는 (3)을 선택하지만, 한 단계 더 나아가 HTML 표현의 키 이름도 변경합니다.
일반적으로 특정 구현 하나에만 영향을 미치는 버그 때문에 사양을 변경하지는 않습니다. 단, 이 경우처럼 사양 자체에 문제가 있는 경우는 예외입니다. 여기서는 사양이 올바르며, 단지 pip와 PyPI에 실제 버그가 있을 뿐입니다.
그러나 다음 네 가지 이유로 이렇게 하기로 선택했습니다.
- pip와 PyPI에 함께 영향을 미치는 버그는 다른 어떤 클라이언트와 저장소의 조합보다 불균형적으로 큰 영향을 미칩니다.
- 손상되었을 때의 영향은 어떤 방식으로든 점진적으로 성능이 저하되는 것이 아니라 설치가 전혀 작동하지 않는다는 것입니다.
- 이러한 버그로 차단된 기능은 pip를 사용하여 PyPI에서 종속성을 빠르고 효율적으로 해결하는 능력에 매우 중요합니다. 또한 손상된 pip 버전이 사용되지 않게 될 때까지 오랜 기간 기다리며 이 기능을 지연해야 한다면 전체 생태계에 해가 됩니다.
- 이 기능에 대한 지원이 널리 퍼져 있다고 생각하지 않으므로 사양 변경의 단점은 상당히 제한적이며, 따라서 제한된 수의 프로젝트에만 영향을 미칩니다.
사양
이 문서에서 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY” 및 “OPTIONAL”” 키워드는 RFC 2119에 설명된 대로 해석해야 합니다.
서버
Simple API의 HTML 표현에서 PEP 658메타데이터를 사용하는 경우, 지원되는 값은 그대로 유지하면서 data-core-metadata라는 속성 이름을 사용하여 제공해야 MUST 합니다.
Simple API의 PEP 691JSON 표현에서 PEP 658메타데이터를 사용하는 경우, 지원되는 값은 그대로 유지하면서 core-metadata라는 키를 사용하여 제공해야 MUST 합니다.
이전 키 이름을 사용한 클라이언트를 지원하기 위해 HTML 표현은 data-dist-info-metadata를 사용하여 제공할 수도 MAY 있으며, 그렇게 하는 경우 해당 값은 data-core-metadata의 값과 일치해야 MUST 합니다.
클라이언트
Simple API의 HTML 표현을 사용하는 클라이언트는 PEP 658 메타데이터가 존재하는 경우 키 data-core-metadata에서 해당 메타데이터를 반드시 읽어야 합니다. 해당 키가 존재하지만 data-core-metadata가 존재하지 않는 경우 레거시 data-dist-info-metadata를 선택적으로 사용할 수 있습니다.
Simple API의 JSON 표현을 사용하는 클라이언트는 PEP 658 메타데이터가 존재하는 경우 키 core-metadata에서 해당 메타데이터를 반드시 읽어야 합니다. 해당 키가 존재하지만 core-metadata가 존재하지 않는 경우 레거시 dist-info-metadata키를 선택적으로 사용할 수 있습니다.
하위 호환성
이 PEP에는 사소한 호환성 문제가 있습니다. 현재 기존 메타데이터 키를 올바르게 처리하는 클라이언트가 새로운 메타데이터 키를 자동으로 이해하지는 못하지만, 정상적으로 기능을 축소하고 PEP 658 메타데이터가 존재하지 않는 것처럼 동작해야 합니다.
그 외에는 이 PEP와 관련된 호환성 문제가 없어야 합니다.
거부된 아이디어
사양을 변경하지 않고 PyPI 및/또는 pip에서 수정하는 방법을 모색합니다.
우리는 PEP 658이 가져온 개선 사항이 PyPI에서 의존성을 해결하는 성능을 향상하는 데 매우 중요하다고 믿으며, 이를 가능한 한 신속하게 배포할 수 있기를 바랍니다.
안타깝게도 이러한 버그의 특성상, 널리 배포되어 사용되는 pip 버전을 손상하지 않고는 이를 현재 상태 그대로 배포할 수 없습니다. 이 경우의 손상은 영향을 받는 사용자가 문제를 해결하기 위해 pip 버전을 직접 업그레이드할 수도 없고, 먼저 다른 방법으로 pip를 수동으로 가져와야 할 정도로 심각합니다(예: get-pip.py).
PyPI는 해당 사용자들을 위한 이러한 손상을 완화할 방법 없이는 이 작업을 수행하지 않으려 할 것입니다. 합리적인 완화 전략이 없다면, PyPI에서 해당 pip 버전이 더 이상 사용되지 않을 때까지 기다려야 하며, 이는 아마도 지금으로부터 5년 이상 걸릴 것입니다.
사용할 수 있는 완화 전략은 몇 가지 있지만, 이들 역시 거부했습니다.
완화: pip를 특별히 처리하기
손상이 특히 심각한 이유는 사용자가 손상되지 않은 pip 버전을 얻기 위해 pip를 업그레이드하는 것조차 방지하기 때문이며, 따라서 pip install --upgrade pip와 같은 명령이 실패합니다. PyPI가 pip 자체를 특별히 처리하도록 하여 JSON 엔드포인트가 PEP 658 메타데이터를 절대 반환하지 않게 하면 위의 명령이 계속 작동하도록 완화할 수 있습니다.
이 PEP에서는 pip만 업그레이드하는 간단한 명령은 작동하더라도, 사용자가 해당 명령에 업그레이드할 다른 항목을 무엇이든 포함하면 명령이 다시 실패하게 되므로 이 아이디어를 거부합니다. 이는 여전히 손상이 너무 크다고 판단합니다.
또한 이 버그가 현재 PyPI에서 드러나고 있기는 하지만, 실제로는 PEP 658 메타데이터를 올바르게 노출하는 모든 PEP 691 저장소에서 발생할 수 있는 버그입니다. 이는 모든 저장소가 pip를 위한 이 특별한 처리를 포함해야 한다는 의미입니다.
완화: 서버가 User-Agent 감지를 사용하도록 하기
pip은 버전 번호를 User-Agent에 넣으므로, 서버는 버전 번호를 감지하고 해당 버전 번호에 따라 서로 다른 응답을 제공하여 손상된 pip 버전에는 PEP 658 메타데이터를 제공하지 않을 수 있습니다.
이 PEP에서는 User-Agent 감지를 합리적인 방식으로 구현하기가 너무 어렵기 때문에 이 아이디어를 거부합니다.
- PyPI에서는 CDN에 Simple API를 캐시하는 데 크게 의존합니다.
User-Agent에 따라 응답을 달리하면 동일한 콘텐츠에 대한 캐시 키가 CDN 캐시에 폭발적으로 증가하여, 특정 요청이 캐시되지 않고 백엔드 서버에 도달할 가능성이 커집니다. 그러면 부하를 지원하기 위해 백엔드 서버를 훨씬 더 크게 확장해야 합니다. - PyPI는 요청의
Accept헤더를 변경하여 해당 버전들이 HTML 버전만 허용하는 것처럼 보이게 함으로써, CDN의 캐시 키를 유지하면서User-Agent감지 아이디어를 지원할 수도 있습니다. 그러나 이는 pip의 HTTP 캐시를 비롯한 PyPI의 모든 하위 캐시에는 영향을 주지 않습니다. 해당 요청에 대한 JSON 버전이 캐시되어 있을 수 있고, 이러한 캐시를 공유해도 허용되지 않는다는 사실을 하위 캐시가 알 수 있도록User-Agent에 대한Vary를 내보내지도 않기 때문입니다. 하위 캐시에Vary: User-Agent를 추가하면 (1)과 동일한 문제가 발생하지만, 이는 CDN 캐시가 아닌 하위 캐시에 해당합니다. - pip 버그는 궁극적으로 PyPI에만 해당하는 것이 아니라, PEP 691과 PEP 658을 함께 구현하는 모든 저장소에 영향을 줍니다. 이는 구현별 수정에 의존하는 우회 방법을 두 기능을 모두 구현하는 각 저장소에 복제해야 한다는 의미이며, 모든 경우에 쉽거나 가능한 것은 아닙니다(예를 들어 정적 미러는 이러한
User-Agent감지를 수행하지 못할 수 있습니다).
JSON 키만 변경하기
pip의 버그는 Simple API의 JSON 표현에만 영향을 미치므로, 실제로 변경할 필요가 있는 것은 JSON의 키뿐이며 기존 HTML 키는 그대로 둘 수 있습니다.
이 PEP는 장기적으로 HTML과 JSON의 키 이름이 서로 달라지면 이와 같은 실수가 발생할 가능성이 커지고 사양을 구현하고 이해하는 일이 더 혼란스러워질 것이라고 판단하므로 그렇게 하는 것을 거부합니다.
HTML 키를 변경하지 않으려는 주된 이유는 이미 이를 지원하고 있을 수 있는 HTML 전용 클라이언트나 저장소에서 PEP 658 지원을 잃지 않기 위해서입니다. 이 PEP는 클라이언트와 서버 모두 두 키를 계속 지원할 수 있도록 허용하고, 언제 어떻게 그렇게 할지 권고함으로써 이러한 호환성 손상을 완화합니다.
권고 사항
이 고지 자체를 제외한 이 절의 권고 사항은 비규범적이며, 이 PEP를 구현하는 무언가에 가장 적합한 기본 구현 결정이라고 PEP 작성자들이 판단하는 내용을 나타내지만, 이러한 결정을 반드시 따를 것을 요구하는 것은 아닙니다.
서버
특히 버그 자체가 JSON에만 영향을 미쳤으므로, 서버는 더 새로운 키만 내보내도록 권장합니다.
HTML을 사용하고 이를 구현한 클라이언트에서 PEP 658을 지원하려는 서버는 두 키를 HTML에서만 안전하게 내보낼 수 있습니다.
서버에 액세스하는 데 문제가 있는 pip 버전이 사용되지 않을 것이라고 확신하는 경우가 아니라면, 서버는 JSON에서 이전 키를 내보내서는 안 됩니다.
클라이언트
클라이언트는 HTML과 JSON 모두에서 두 키를 지원하고, 이 PEP에서 요구하는 대로 더 새로운 키를 우선하도록 권고합니다. 이를 통해 클라이언트는 PEP 658 및 PEP 691를 이미 올바르게 구현했지만 이 PEP는 구현하지 않은 저장소를 지원할 수 있습니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.