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를 통해 제공되는 아티팩트의 코어 메타데이터 파일을 호스팅하는 메커니즘을 명세하였으며, 이를 통해 클라이언트는 아티팩트 전체를 다운로드하지 않고도 메타데이터를 가져와 사용할 수 있습니다. 이후 Simple API에서 HTML 대신 JSON을 사용할 수 있는 기능을 추가하기 위해 PEP 691이 작성되었으며, 여기에는 PEP 658 메타데이터에 대한 지원도 포함되었습니다.
안타깝게도 PyPI는 아주 최근까지 PEP 658을 지원하지 않았고, 이 지원은 PEP 658의 dist-info-metadata 키가 JSON 표현에서 data-dist-info-metadata로 잘못 명명되는 버그와 함께 릴리스되었습니다. 그러나 이 버그를 수정하려고 시도하던 중, pip 역시 버그를 가지고 있다는 사실이 발견되었습니다. 이 버그로 인해 JSON 표현에서 dist-info-metadata를 사용하기만 하면 pip가 예외를 일으키며 완전히 실패합니다.
pip의 이 버그는 적어도 v22.3부터 존재해 왔으며, 이는 약 8개월 동안 릴리스된 상태였다는 뜻입니다. 이는 Python 릴리스와 다운스트림 Linux 릴리스에 포함되고, 컨테이너, 가상 환경 등에 내장되기에 충분히 긴 기간입니다.
이로 인해 우리는 곤란한 처지에 놓이게 되었습니다. PyPI의 버그를 수정하면 pip의 버그 때문에 pip가 망가지므로 수정할 수 없는데, 해당 pip 버전은 이미 널리 배포되었을 만큼 오래되었습니다. 설상가상으로, 이런 식으로 망가진 pip 버전은 PyPI가 버그를 수정하고 나면 PyPI에서 아무것도 설치할 수 없게 되며, 여기에는 수정된 새 버전의 pip를 설치하는 것도 포함됩니다.
근거
이 버그들을 수정하기 위한 향후 방향으로는 크게 3가지 선택지가 있습니다:
- 사양을 변경하지 않고, pip의 버그를 수정하고, 어느 정도 시간을 기다린 뒤 PyPI의 버그를 수정합니다. 이 경우 수정되지 않은 pip를 사용하는 모든 사람이 PyPI에서 새 pip조차 설치할 수 없게 됩니다.
- (1)과 동일하게 하되, PyPI에 특수 처리를 두어 PEP 658 메타데이터가 있더라도 pip에는 이를 내보내지 않도록 합니다. 이렇게 하면 망가진 버전을 사용하는 사람들이 pip를 업그레이드할 수는 있지만, 그 밖의 것은 할 수 없습니다.
- 사양을 변경하여 pip가 현재 처리하지 못하는 키를 피하고, PyPI가 그 키를 내보낼 수 있게 하며, 그 키를 활용하는 새 버전의 pip를 릴리스할 수 있게 합니다.
이 PEP는 (3)을 선택하되, 한 걸음 더 나아가 HTML 표현의 키 이름도 변경합니다.
일반적으로 우리는 사양 자체에 결함이 있는 경우가 아니라면 특정 구현 하나에만 영향을 미치는 버그 때문에 사양을 변경하지 않습니다. 이번 경우는 그렇지 않습니다. 사양에는 문제가 없으며, 이것들은 단지 pip와 PyPI의 실제 버그일 뿐입니다.
그러나 우리는 다음 4가지 이유로 이렇게 하기로 합니다:
- pip와 PyPI에 함께 영향을 미치는 버그는 다른 어떤 클라이언트와 저장소의 조합과 비교해도 지나치게 큰 영향을 미칩니다.
- 문제가 생겼을 때의 영향은 설치가 어떤 식으로든 기능이 점진적으로 저하되는 데 그치지 않고, 아예 전혀 작동하지 않는다는 점입니다.
- 이 버그들로 인해 막혀 있는 기능은 pip로 PyPI의 의존성을 빠르고 효율적으로 해결하는 데 매우 중요하며, 망가진 버전의 pip가 더 이상 사용되지 않을 때까지 기다리느라 이 기능을 오랫동안 미뤄야 한다면 생태계 전체에 해가 될 것입니다.
- 이에 대한 지원이 널리 퍼져 있지 않다고 판단되므로 사양 변경의 단점은 상당히 제한적이며, 영향을 받는 프로젝트의 수도 제한적입니다.
명세
이 문서의 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”” 키워드는 RFC 2119에 설명된 대로 해석해야 합니다.
서버
PEP 658 메타데이터를 Simple API의 HTML 표현에서 사용할 때는 속성 이름 data-core-metadata를 사용하여 내보내야 하며(MUST), 지원되는 값은 그대로 유지됩니다.
PEP 658 메타데이터를 Simple API의 PEP 691 JSON 표현에서 사용할 때는 키 core-metadata를 사용하여 내보내야 하며(MUST), 지원되는 값은 그대로 유지됩니다.
이전 키 이름을 사용하던 클라이언트를 지원하기 위해 HTML 표현은 data-dist-info-metadata를 사용하여 내보낼 수도 있으며(MAY), 그렇게 하는 경우 그 값은 data-core-metadata의 값과 일치해야 합니다(MUST).
클라이언트
Simple API의 HTML 표현 중 어느 것이든 사용하는 클라이언트는 data-core-metadata 키가 있으면 이 키에서 PEP 658 메타데이터를 읽어야 합니다(MUST). data-core-metadata는 없지만 레거시 data-dist-info-metadata가 있다면, 클라이언트는 선택적으로 이를 사용할 수 있습니다(MAY).
Simple API의 JSON 표현을 사용하는 클라이언트는 core-metadata 키가 있으면 이 키에서 PEP 658 메타데이터를 읽어야 합니다(MUST). core-metadata는 없지만 레거시 dist-info-metadata 키가 있다면, 클라이언트는 선택적으로 이 키를 사용할 수 있습니다(MAY).
하위 호환성
이 PEP에는 사소한 호환성 단절이 있습니다. 현재 기존 메타데이터 키를 올바르게 처리하는 클라이언트는 새 메타데이터 키를 자동으로 이해하지 못합니다. 다만 이러한 클라이언트는 문제없이 기능을 축소하여 PEP 658 메타데이터가 존재하지 않는 것처럼 동작할 것입니다.
그 밖에는 이 PEP로 인한 호환성 문제가 없을 것입니다.
기각된 아이디어
명세를 변경하지 않고 PyPI 및/또는 pip에서 수정하여 대처하기
저희는 PEP 658이 가져오는 개선이 PyPI에서 의존성을 해석하는 성능을 높이는 데 매우 중요하다고 믿으며, 가능한 한 빨리 이를 배포할 수 있기를 바랍니다.
안타깝게도 이 버그들의 특성상, 널리 배포되어 사용 중인 pip 버전들을 망가뜨리지 않고는 현재 상태 그대로 배포할 수 없습니다. 이 경우 발생하는 문제는 매우 심각하여, 영향을 받는 사용자는 이를 고치기 위해 pip 버전을 직접 업그레이드할 수조차 없고, 먼저 다른 방법(예: get-pip.py)으로 pip를 수동으로 받아와야 합니다.
해당 사용자들이 겪을 문제를 완화할 방법이 없다면 PyPI는 이를 받아들이지 않을 것입니다. 합리적인 완화 전략이 없다면, 해당 pip 버전들이 PyPI에서 더 이상 사용되지 않을 때까지 기다려야 하며, 이는 아마도 지금부터 5년 이상 걸릴 것입니다.
사용할 수 있는 완화 전략이 몇 가지 있지만, 저희는 이 전략들도 거부했습니다.
완화 방안: pip를 특별 취급하기
이 문제는 사용자가 망가지지 않은 pip 버전을 얻기 위해 pip를 업그레이드하는 것조차 막는다는 점에서 특히 심각하며, 따라서 pip install --upgrade pip 같은 명령도 실패합니다. PyPI가 pip 자체를 특별 취급하여 JSON 엔드포인트가 pip에 대해서는 PEP 658 메타데이터를 절대 반환하지 않도록 하면, 이 문제를 완화하고 위 명령이 계속 동작하게 할 수 있습니다.
이 PEP는 이 아이디어를 거부합니다. pip만 업그레이드하는 단순한 명령은 동작하겠지만, 사용자가 그 명령에 업그레이드할 대상을 하나라도 더 포함하면 명령은 다시 실패하게 되며, 저희는 이것이 여전히 너무 큰 문제라고 판단하기 때문입니다.
또한 이 버그가 지금은 우연히 PyPI에서 드러나고 있지만, 실제로는 PEP 658 메타데이터를 올바르게 노출하는 모든 PEP 691 저장소에서 발생할 수 있는 버그입니다. 이는 모든 저장소가 pip에 대한 이 특별 처리를 갖추어야 한다는 뜻입니다.
완화 방안: 서버에서 User-Agent 감지 사용하기
pip는 자신의 버전 번호를 User-Agent에 넣습니다. 따라서 서버는 이 버전 번호를 감지하여 버전에 따라 다른 응답을 제공할 수 있고, 이를 통해 망가진 pip 버전에는 PEP 658 메타데이터를 제공하지 않을 수 있습니다.
이 PEP는 이 아이디어를 거부합니다. User-Agent 감지를 지원하는 것은 합리적인 방식으로 구현하기에 너무 어렵기 때문입니다.
- PyPI는 Simple API를 CDN에 캐시하는 데 크게 의존합니다.
User-Agent에 따라 응답을 다르게 하면, CDN 캐시에서 같은 콘텐츠에 대한 캐시 키가 폭발적으로 늘어납니다. 그러면 특정 요청이 캐시되지 않고 백엔드 서버로 넘어갈 가능성이 높아지며, 백엔드 서버는 그 부하를 감당하기 위해 훨씬 크게 확장되어야 합니다. - PyPI는 해당 버전들이 HTML 버전만 받아들이는 것처럼 보이도록 요청의
Accept헤더를 변경하여, CDN의 캐시 키를 유지하면서User-Agent감지 아이디어를 지원할 수는 있습니다. 하지만 이 방법은 PyPI 하위의 캐시에는 영향을 주지 못합니다. 여기에는 pip의 HTTP 캐시도 포함되는데, 이 캐시에는 해당 요청에 대한 JSON 버전이 캐시되어 있을 수 있습니다. 또한 저희는User-Agent에 대한Vary를 내보내지 않으므로, 하위 캐시는 그 캐시를 공유하면 안 된다는 사실을 알 수 없습니다. 그렇다고 하위 캐시를 위해Vary: User-Agent를 추가하면, CDN 캐시 대신 하위 캐시에서 (1)과 같은 문제가 발생합니다. - 결국 이 pip 버그는 PyPI에만 해당하는 문제가 아니며, PEP 691과 PEP 658을 함께 구현하는 모든 저장소에 영향을 줍니다. 즉, 구현별 수정에 의존하는 우회 방법은 두 PEP를 모두 구현하는 저장소마다 되풀이해야 하며, 이는 모든 경우에 쉽거나 가능하지는 않을 수 있습니다(예를 들어 정적 미러는 이러한
User-Agent감지를 수행하지 못할 수 있습니다).
JSON 키만 변경하기
pip의 버그는 Simple API의 JSON 표현에만 영향을 주므로, 실제로 변경할 필요가 있는 것은 JSON의 키뿐이며 기존 HTML 키는 그대로 둘 수 있습니다.
이 PEP는 그렇게 하는 것을 거부합니다. 장기적으로 HTML과 JSON의 키 이름이 서로 달라지면 이와 같은 실수가 발생할 가능성이 높아지고, 명세를 구현하고 이해하기가 더 혼란스러워질 것이라고 생각하기 때문입니다.
HTML 키를 변경하지 않으려는 주된 이유는 이미 PEP 658을 지원하고 있을 수 있는 HTML 전용 클라이언트나 저장소에서 해당 지원을 잃지 않기 위해서입니다. 이 PEP는 클라이언트와 서버 모두 두 키를 계속 지원할 수 있도록 허용하고, 언제 어떻게 그렇게 해야 하는지에 대한 권장 사항을 제시함으로써 그러한 호환성 손상을 완화합니다.
권장 사항
이 안내 자체를 제외한 이 절의 권장 사항은 비규범적이며, 이 PEP를 구현하는 대상에 대해 PEP 작성자들이 최선의 기본 구현 결정이라고 생각하는 바를 나타낼 뿐, 이러한 결정을 따라야 한다는 어떠한 요구 사항도 나타내지 않습니다.
서버
서버는 새로운 키만 내보낼 것을 권장합니다. 버그 자체가 JSON에만 영향을 미쳤으므로, 특히 Simple API의 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.