Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 470 – PyPI의 외부 호스팅 지원 제거

Author:
Donald Stufft <donald at stufft.io>
BDFL-Delegate:
Paul Moore <p.f.moore at gmail.com>
Discussions-To:
Distutils-SIG list
Status:
Final
Type:
Process
Topic:
Packaging
Created:
12-May-2014
Post-History:
14-May-2014, 05-Jun-2014, 03-Oct-2014, 13-Oct-2014, 26-Aug-2015
Replaces:
438
Resolution:
Distutils-SIG message

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 PyPI 외부에 파일을 호스팅하는 기능에 대한 지원을 폐지하고 제거할 것을 제안합니다. 아울러 PEP 438에서 추가된 기능, 특히 여러 종류의 링크를 분류하기 위한 rel 정보와 API 버전을 나타내기 위한 meta 태그의 폐지 및 제거도 제안합니다.

근거

역사적으로 PyPI에는 파일을 호스팅하는 방법도, 설치 가능한 파일을 자동으로 가져오는 방법도 없었습니다. 대신 PyPI는 이름 충돌을 방지하기 위한 중앙 이름 레지스트리를 제공하고, 사용할 프로젝트를 찾는 탐색 수단을 제공하는 데 초점을 맞추었습니다. 시간이 흐르면서 setuptools는 자동으로 내려받아 설치할 수 있는 것을 찾기 위해 사람이 보도록 만든 이 페이지들과 이 페이지들에서 링크된 페이지들을 스크랩하기 시작했습니다. 이것이 결국 “Simple” API가 되었습니다. Simple API는 비슷한 URL 구조를 사용했지만, API의 효율을 높이기 위해 불필요한 링크와 정보를 모두 없앴습니다. 또한 PyPI에는 프로젝트가 릴리스 파일을 PyPI에 직접 업로드하는 기능이 생겼습니다. 이에 따라 PyPI는 색인뿐 아니라 저장소 역할도 할 수 있게 되었습니다.

이로써 PyPI는 Python 생태계에서 똑같이 중요한 두 가지 역할을 맡게 됩니다. 하나는 Python 프로젝트를 쉽게 찾을 수 있게 하는 색인 역할이고, 다른 하나는 Python 프로젝트를 쉽게 호스팅하고 내려받고 설치할 수 있게 하는 중앙 저장소 역할입니다. PyPI가 지나온 역사와 매우 유기적으로 이루어진 성장 때문에 이 두 역할 사이의 경계는 모호합니다. 이 모호함은 두 역할의 최종 사용자 모두에게 혼란을 주었고, 이는 다시 PyPI를 서로 다른 용도로 사용하려는 사람들 사이에 불만을 불러왔습니다. 이런 일은 대개 최종 사용자는 PyPI를 저장소로 사용하려 하지만 작성자는 PyPI를 색인으로만 사용하려 할 때 일어납니다.

이 혼란은 결국 프로젝트의 최종 사용자가 그 프로젝트가 PyPI에 호스팅되어 있는지, 아니면 외부 서비스에 의존하는지를 알지 못하는 데서 비롯됩니다. 이 문제는 흔히 PyPI는 정상인데 외부 서비스가 중단되었을 때 드러납니다. 사람들은 PyPI도 동작하고 다른 프로젝트들도 동작하는데 유독 이 프로젝트 하나만 동작하지 않는 것을 보게 됩니다. 이들은 문제를 해결하려면 누구에게 연락해야 하는지, 어떤 조치를 취해야 하는지 모르는 경우가 많습니다.

PEP 438은 프로젝트가 저장소 기능을 사용하는지 여부를 명시적으로 선언할 수 있게 하고, 사용하지 않는 경우에는 설치 프로그램이 발견한 링크를 “내부”, “검증 가능한 외부”, “검증 불가능한 외부” 중 하나로 분류하도록 하여 이 문제를 해결하려 했습니다. PEP 438은 승인되어 pip 1.4(2013년 7월 23일 릴리스)에 구현되었으며, 최종 전환은 pip 1.5(2014년 1월 2일 릴리스)에 구현되었습니다.

PEP 438은 더 많은 사람이 PyPI의 저장소 기능을 활용하도록 하는 데 성공했습니다. PyPI를 뒷받침하는 전 세계 CDN이 많은 사람에게 속도 향상을 제공한다는 점에서 이는 전반적으로 좋은 일이었습니다. 그러나 그 과정에서 최종 사용자와 작성자 모두에게 새로운 혼란과 고충을 안겨 주었습니다.

명시적인 다중 저장소 사용으로 옮겨 가면 이 두 역할 사이의 경계를 훨씬 더 명확하게 만들 수 있습니다. 또한 PyPI를 저장소로 사용하고 싶지 않은 사람들을 처리하는 현재 구현 방식이 일으키는 “숨겨진” 의외의 동작을 없앨 수 있습니다.

주요 사용자 경험 기대 사항

  1. 시스템, 사용자 또는 가상 환경 수준에서 적절히 설정되어 있으면 외부 호스팅이 “그냥 동작”하도록 쉽게 허용합니다.
  2. 혼란스러운 “verifiable external”과 “unverifiable external” 구분에 대한 언급을 사용자 경험에서(패키지를 설치할 때와 릴리스할 때 모두) 빠짐없이 없앱니다.
  3. PyPI의 저장소 측면은 그저 기본 패키지 호스팅 위치가 되어야 합니다(즉, 대부분의 클라이언트 도구가 기본 설정에서 옵트인이 아니라 옵트아웃으로 취급하는 유일한 위치여야 합니다). 그 측면을 제외하면, PyPI에 호스팅한다고 해서 자체 패키지 저장소에 호스팅하는 것보다 더 나은 사용자 경험을 제공해서는 안 됩니다.
  4. 이 모든 것을 수행하면서도, 국가 수준의 적대자에 미치지 않는 대부분의 공격자에 대해 안전한 기본 동작을 제공합니다.

왜 추가 저장소입니까?

널리 쓰이는 두 설치 프로그램 도구인 pip와 easy_install/setuptools는 모두 설치 요구 사항을 충족하는 파일을 찾기 위한 추가 검색 위치라는 개념을 지원하며, 이미 수년 전부터 이를 지원해 왔습니다. 따라서 새로운 플래그나 개념을 단계적으로 도입할 필요가 없으며, PyPI가 아닌 저장소에서 프로젝트를 설치하는 해결책은 최종 사용자의 설치 프로그램이 (합리적인 범위 내에서) 얼마나 오래되었든 관계없이 제대로 기능(함수)합니다. 이 개념은 Python 도구에 꽤 오래전부터 있었을 뿐 아니라 여러 언어에 걸쳐 존재하며 OS 수준으로까지 확장됩니다. OS 패키지 도구는 거의 예외 없이 다중 저장소 지원을 사용하므로, 사람들이 이미 이 개념에 익숙할 가능성이 매우 높습니다.

또한 다중 저장소 방식은 PyPI의 색인 부분에는 포함되고 싶지만 PyPI의 저장소 부분은 활용하고 싶지 않은 프로젝트를 허용한다는 좁은 범위 밖에서도 유용한 개념입니다. 여기에는 회사가 내부 패키지를 담은 저장소를 호스팅하려는 경우나, 프로젝트가 알파, 베타, 릴리스 후보, 최종 릴리스처럼 여러 릴리스 “채널”을 두려는 경우가 포함됩니다. 이 방식은 수 기가바이트짜리 데이터 파일이나, 적어도 현재로서는 Linux Wheel처럼 PyPI에 업로드할 수 없는 파일을 호스팅하려는 프로젝트에도 사용할 수 있습니다.

왜 PEP 438이나 그와 비슷한 방식이 아닙니까?

추가 검색 위치 지원은 pip와 setuptools에 꽤 오래전부터 있었지만, PEP 438 지원은 pip에만 1.4 버전부터 들어갔으며 setuptools에는 아직 구현되지 않았습니다. PEP 438의 설계 덕분에 오래된 설치 프로그램을 사용하더라도 외부 파일이 필요하지 않은 프로젝트에 대해서는 사용자가 여전히 이점을 누릴 수 있었습니다. 그러나 외부 파일이 실제로 필요한 프로젝트의 경우, 사용자는 여전히 잠재적으로 신뢰할 수 없거나, 더 나쁘게는 안전하지 않은 파일을 아무런 알림 없이 내려받게 됩니다. 또한 이 체계는 PyPI의 역사에서 비롯되었으므로 Python에만 있습니다. 따라서 사용자 대부분은, 어쩌면 모든 사용자가 Python 도구 체인을 사용하다가 이 개념을 직접 마주치기 전까지는 이를 낯설어할 것이 거의 확실합니다.

게다가 PEP 438이 제안한 분류 체계는 실제로 최종 사용자에게 극도로 혼란스러운 것으로 드러났습니다. 그 정도가 너무 심해서, 이 PEP는 현재 상황을 결코 유지할 수 없다는 입장입니다. 이 체계에서 사용자가 흔히 겪는 과정은 다음과 같습니다. 먼저 프로젝트를 설치하려고 하면 오류 메시지를 받을 수 있습니다(프로젝트가 예전에 PyPI에 무언가를 업로드했다가 이전 파일을 지우지 않은 채 나중에 다른 방식으로 옮겼다면 받지 않을 수도 있습니다). 오류 메시지가 --allow-external을 제안하는 것을 보고 그 플래그를 추가해 명령을 다시 실행하면 십중팔구 또 다른 오류 메시지를 받습니다. 이번에는 오류 메시지가 --allow-unverified도 추가하라고 제안하는 것을 보고 명령을 세 번째로 실행한 끝에야 비로소 원하던 것을 설치하게 됩니다.

이러한 UX 실패에는 여러 원인이 있습니다.

  1. pip는 Simple API에서 프로젝트의 파일을 하나라도 찾으면 더 찾으려 하지 않고 그 파일을 그대로 사용합니다. 더 찾으려 하면 PEP 438의 이점이 상당 부분 사라지므로 이것은 일반적으로 올바른 동작입니다. 즉, 사용자가 설치를 요청한 것과 일치하는 파일을 프로젝트가 한 번이라도 업로드한 적이 있다면, 그 파일이 얼마나 오래되었든 상관없이 그 파일이 사용됩니다.
  2. PEP 438은 대부분의 프로젝트가 PyPI에 직접 업로드하거나 릴리스 파일에 직접 링크하도록 방식을 바꿀 것이라고 암묵적으로 가정합니다. 결국 많은 프로젝트가 PyPI에 업로드하기로 결정한 것은 사실이지만, 그중 일부는 PEP 438을 둘러싼 UX가 너무 나빠서 그렇게 할 수밖에 없다고 느꼈기 때문에 업로드했을 뿐입니다. 그런데 더 우려스러운 점은 파일에 직접 안전하게 링크하는 방식을 택한 프로젝트가 매우 적다는 사실입니다. 대부분은 여전히 실제 파일을 찾으려면 스크레이핑해야 하는 페이지에 링크할 뿐이어서, 안전한 방식(--allow-external)은 대체로 쓸모가 없어졌습니다.
  3. 작성자가 자신의 파일에 직접 링크하려고 하더라도 이를 안전하게 하는 방법은 잘 알려져 있지 않습니다. 그렇게 하려면 (역사적인 이유로) URL의 해시 부분에 MD5 해시를 넣어야 합니다. 이를 넣지 않으면 해당 파일은 “검증되지 않은” 파일로 간주됩니다.
  4. PEP 438은 보안을 중심에 두는 관점을 취하므로, 검증되지 않은 프로젝트를 전역적으로 옵트인하는 방법은 어떤 형태로든 허용하지 않습니다. 이는 대체로 바람직하지만, 다음과 같이 극도로 장황하고 반복적인 명령을 입력해야 하는 결과를 낳습니다.:
    $ pip install --allow-external myproject --allow-unverified myproject myproject
    $ pip install --allow-all-external --allow-unverified myproject myproject
    

다중 저장소/색인 지원

설치 프로그램은 설치 프로그램이 여러 URL 위치를 가리키도록 하는 기능을 구현하거나 계속 제공해야 합니다(SHOULD). 사용자가 추가 위치를 사용하겠다는 뜻을 나타내는 구체적인 메커니즘은 각 구현에 맡깁니다.

여러 저장소를 사용할 때 설치 후보를 찾는 메커니즘도 각 구현에 맡깁니다. 다만 저장소를 한번 설정하고 나면, 구현은 기본 저장소가 아니라는 이유만으로 그 저장소의 사용을 만류하거나 경고하거나 그 밖에 부정적으로 비치게 해서는 안 됩니다.

현재 pip와 setuptools는 모두 어느 저장소에서든 찾을 수 있는 가장 좋은 설치 후보를 사용하는 방식으로 다중 저장소 지원을 구현합니다. 사실상 여러 저장소를 하나의 큰 저장소처럼 취급하는 것입니다.

설치 프로그램은 또한 기본 저장소를 제거하거나 그 밖의 방법으로 기본 저장소의 사용을 비활성화하는 메커니즘을 구현해야 합니다(SHOULD). 이를 구체적으로 어떻게 달성할지는 각 구현에 맡깁니다.

설치 프로그램은 또한 사용자가 특정 저장소에서 설치하고자 하는 프로젝트를 화이트리스트 및 블랙리스트로 지정하는 메커니즘을 구현해야 합니다(SHOULD). 이를 구체적으로 어떻게 달성할지는 각 구현에 맡깁니다.

Python 패키징 가이드에는 자체 저장소를 구축하는 방법들을 자세히 설명하는 절을 추가해야 합니다(MUST). 그러면 앞으로 PyPI에서 호스팅하지 않으려는 프로젝트는 누구나 그 문서를 참조할 수 있습니다. 여기에는 자체 저장소 호스팅에 의존하는 프로젝트가 프로젝트 설명에 프로젝트 설치 방법을 적어 두어야 한다는 권고도 포함해야 합니다.

링크 스파이더링의 폐지 및 제거

PyPI에 새로운 호스팅 모드가 추가됩니다. 이 호스팅 모드의 이름은 pypi-only이며, PEP 438이 이미 제공한 세 가지 모드인 pypi-explicit, pypi-scrape, pypi-scrape-crawl에 더해 추가됩니다. 이 새로운 호스팅 모드는 프로젝트의 simple api 페이지를 수정해서, PyPI에 직접 호스팅된 파일만 나열하고 그 밖의 어떤 것에도 링크하지 않도록 합니다.

이 PEP가 승인되고 pypi-only 모드가 추가되면 모든 신규 프로젝트는 기본적으로 PyPI 전용 모드로 설정됩니다. 또한 이 모드로 고정되어 해당 설정을 변경할 수 없게 됩니다.

그런 다음 PyPI에서만 호스팅되는 모든 프로젝트에 이메일을 보내, 한 달 후 프로젝트가 자동으로 pypi-only 모드로 전환된다는 사실을 알립니다. 이 이메일을 보내고 한 달이 지나면, 이메일을 받은 프로젝트 중 여전히 PyPI에서만 호스팅되는 프로젝트는 모드가 영구적으로 pypi-only로 설정됩니다.

동시에 PyPI 외부 호스팅에 의존하는 프로젝트에도 이메일을 보냅니다. 이 이메일은 해당 프로젝트들에게 외부 호스팅 파일이 PyPI에서 폐지되었으며, 이메일 발송 시점으로부터 3개월 후에 모든 외부 링크가 설치 프로그램용 API에서 제거될 것임을 경고합니다. 이 이메일에는 프로젝트를 PyPI에서 호스팅하도록 전환하는 방법에 대한 안내가 반드시 포함되어야 합니다. 또한 스크립트나 패키지의 링크도 반드시 포함되어야 합니다. 이 스크립트나 패키지에 PyPI 자격 증명과 패키지 이름을 입력하면 모든 파일을 자동으로 내려받아 PyPI에 다시 호스팅합니다. 이 이메일에는 자체 색인 페이지를 구성하는 방법에 대한 안내도 반드시 포함되어야 합니다. 많은 사용자가 오래전에 가입하여 약관 내용을 기억하지 못할 수 있으므로, 이 이메일에는 PyPI 서비스 약관 링크도 포함되어야 합니다. 마지막으로 이 이메일에는 PyPI에 등록된 링크 중 설치 가능한 파일이 있는 것으로 감지된 링크의 목록도 포함되어야 합니다.

첫 이메일을 보내고 두 달이 지나면, 여전히 외부 호스팅에 의존하는 모든 프로젝트에 또 다른 이메일을 보내야 합니다. 이 이메일에는 첫 이메일에 담긴 정보가 모두 동일하게 포함되지만, 제거 일자는 3개월 후가 아니라 한 달 후가 됩니다.

마지막으로 그로부터 한 달 후 모든 프로젝트가 pypi-only 모드로 전환되며, 외부 링크 파일 기능을 제거하도록 PyPI가 수정됩니다.

변경 사항 요약

저장소 측

  1. PEP 438에서 정의한 호스팅 모드를 폐지 예정으로 지정한 뒤 제거합니다.
  2. simple API가 저장소 안에 있는 파일만 나열하도록 제한합니다.

클라이언트 측

  1. 다중 저장소 지원을 구현합니다.
  2. 기본 저장소를 제거하거나 비활성화하는 메커니즘을 구현합니다.
  3. PEP 438 폐지 예정 지정 / 제거

영향

영향을 파악하기 위해 pip과 setuptools가 사용하는 방식과 유사한 PyPI 검색 방법으로 모든 프로젝트를 살펴보았습니다. 이 과정에서 PyPI에 있는 파일, PyPI에서 안전하게 링크된 파일, PyPI에서 안전하지 않게 링크된 파일, 마지막으로 PyPI 외부에서 안전하지 않게 제공되는 파일을 모두 검색했습니다. 같은 파일이 여러 위치에서 발견된 경우에는 중복을 제거하고 다음 우선순위에 따라 한 위치에서만 집계했습니다: PyPI > PyPI 외부(안전) > PyPI 외부(안전하지 않음). 이렇게 하면 영향을 가장 넓게 정의하게 됩니다. 이 정의에서는 프로젝트의 파일 중 하나라도 기본적으로 더 이상 보이지 않게 되면 영향을 받는 것으로 봅니다. 하지만 그 파일은 몇 년 전의 것일 수도 있고, PyPI에 sdist가 따로 있는 상황에서의 바이너리 파일일 수도 있습니다. 따라서 실제 영향은 훨씬 작을 가능성이 높지만, 잘못 집계하지 않도록 가장 넓은 정의를 채택합니다.

이 글을 쓰는 시점에 PyPI에는 65,232개의 프로젝트가 호스팅되어 있습니다. 그중 59개는 PyPI 외부에서 안전하게 호스팅되는 외부 파일에 의존하고, 931개는 PyPI 외부에서 안전하지 않게 호스팅되는 외부 파일에 의존합니다. 이는 프로젝트의 1.5%가 이번 변경으로 어떤 식으로든 영향을 받는 반면, 98.5%는 지금까지와 마찬가지로 정상적으로 기능(함수)한다는 것을 보여 줍니다. 또한 영향을 받는 프로젝트 중 PEP 438이 제공하는 기능을 사용하여 PyPI 외부에서 안전하게 호스팅하는 프로젝트는 5%에 불과합니다. 나머지 95%는 중간자 공격(Man In The Middle attack)을 통한 원격 코드 실행(Remote Code Execution)에 사용자를 노출하고 있습니다.

자주 묻는 질문

<X> 때문에 프로젝트를 PyPI에서 호스팅할 수 없습니다. 어떻게 해야 합니까?

먼저 <X>가 PyPI에 본질적으로 내재된 문제인지, 아니면 PyPI가 여러분을 위해 <X>를 해결하는 기능을 추가할 수 있는 문제인지 판단해야 합니다. PyPI가 기능을 추가하여 여러분이 PyPI에서 프로젝트를 호스팅할 수 있게 된다면, 그 기능을 제안하십시오. 그러나 <X>가 자신의 파일에 대한 통제권을 유지하고 싶은 경우처럼 PyPI에 본질적으로 내재된 것이라면, 자체 패키지 저장소를 구축하고 프로젝트 설명에서 사용자들에게 그 저장소를 각자 선택한 설치 프로그램이 사용할 저장소 목록에 추가하도록 안내해야 합니다.

이 PEP 때문에 사용자들의 경험이 이전보다 나빠졌는데, 이를 어떻게 설명해야 합니까?

이 답변의 일부는 개별 프로젝트마다 다를 것입니다. 사용자의 설치 프로그램 기본 저장소 목록에 이미 있는 저장소를 활용하지 않고 자체 저장소에 호스팅하기로 결정한 이유를 사용자에게 설명해야 합니다. 그러나 답변의 또 다른 일부는 다음 내용을 설명하는 것입니다. 외부 링크를 투명하게 포함하던 이전 동작은 보안상 위험 요소(대부분의 경우 MITM이 최종 사용자의 컴퓨터에서 임의의 Python 코드를 실행할 수 있었기 때문입니다)였을 뿐만 아니라 신뢰성 측면에서도 우려 사항이었습니다. PEP 438은 이를 명시적으로 옵트인하게 하여 해결하려 했지만, PEP 438은 그와 함께 여러 심각한 사용성 문제를 가져왔습니다. PEP 470은 이 모델을 많은 사용자에게 익숙하고 Linux 배포판에서 흔히 쓰이는 모델로 단순화한 것입니다.

저장소 구조로 전환하면 제 워크플로가 깨지거나 호스트에서 허용하지 않는 경우에는 어떻게 합니까?

저장소에 필요한 것을 기꺼이 지원해 줄 저렴하거나 무료인 호스트가 많이 있습니다. 특히 파일이 실제로 위치한 곳을 가리키는 올바른 구조의 호스트를 생성할 수만 있다면, 파일을 다른 곳에 따로 업로드할 필요는 없습니다. 이러한 호스트 중 다수는 공유 도메인 이름을 사용하는 무료 HTTPS를 제공하며, 무료 HTTPS 인증서는 StartSSL에서, 또는 가까운 미래에는 LetsEncrypt에서 받을 수 있고, 수많은 업체에서 저렴하게 구할 수도 있습니다.

왜 <X>를 제공하지 않습니까?

이에 대한 답은 <X>가 무엇인지에 따라 달라지지만, 일반적으로 다음 중 하나입니다.

  • 저희가 미처 생각하지 못했고, 이전에 아무도 제안한 적이 없었습니다.
  • 저희는 <X>에 대한 해결책을 제대로 설계할 만큼 충분한 경험이 없으며, 이를 제공하는 데 도움을 줄 해당 분야 전문가를 환영합니다.
  • 저희는 오픈 소스 프로젝트이며, 아직 아무도 <X>를 설계하고 구현하는 일에 자원하지 않았습니다.

추가 기능을 제안하는 추가 PEP는 언제나 환영하지만, <X>를 정확하게 설계할 시간과 전문성을 갖춘 사람이 필요합니다. 이 PEP는 PyPI의 기능이 단순명료해지고, Linux 배포판 저장소와 같은 기존 모델과 유사하여 쉽게 이해할 수 있는 기준선을 갖추는 지점에 도달하는 데 초점을 맞추고 있습니다.

어차피 자체 저장소를 운영한다면 왜 PyPI에 등록해야 합니까?

PyPI는 Python 생태계를 위해 두 가지 핵심 기능(함수)을 수행합니다. 그중 하나는 pip나 다른 패키지 관리자가 실제로 내려받아 설치하는 파일을 위한 중앙 저장소 역할이며, 이 PEP가 다루는 것이 바로 이 기능(함수)이고, 여러분이 자체 저장소를 운영한다면 대체하게 되는 것도 바로 이 기능(함수)입니다. 그러나 PyPI는 이름 충돌을 방지하기 위해 누가 어떤 이름을 소유하는지에 대한 중앙 레지스트리도 제공합니다. Python 패키지를 위한 일종의 DNS라고 생각하면 됩니다. PyPI는 이름이 선착순으로 배정되도록 보장할 뿐만 아니라, 사용자가 새 프로젝트를 찾아보고 검색하고 발견할 수 있는 단일한 장소도 제공합니다. 따라서 간단히 답하자면, 이름 충돌을 피하고 사람들이 여전히 여러분의 프로젝트를 쉽게 발견할 수 있도록 PyPI에 프로젝트를 등록해야 합니다.

거부된 제안

외부에서 호스팅되는 인덱스를 더 쉽게 발견할 수 있도록 하기

이 PEP의 이전 버전에는 PyPI와 설치 프로그램 양쪽에 추가되는 새로운 기능이 포함되어 있었습니다. 이 기능은 프로젝트 작성자가 PyPI에 URL 목록을 입력할 수 있게 하며, 이 목록은 설치 프로그램이 PyPI에 업로드된 파일을 모두 무시하고, 대신 설치가 동작하도록 설치 프로그램에 추가할 수 있는 이러한 추가 URL을 최종 사용자에게 알려 주는 오류를 반환하도록 지시합니다.

이 기능은 PEP 438 해결책에서 수많은 문제를 일으켰던 것과 유사한 UX 문제를 피하는 해결책을 개발하기가 너무 어렵다는 것이 드러났기 때문에 이 PEP의 범위에서 제외되었습니다. 필요하다면 향후 PEP에서 이 아이디어를 다시 검토할 수 있습니다.

현재 분류 체계를 유지하되 선택지를 조정하기

이 PEP는 PEP 438의 전반적인 골자는 유지하면서 현재 시스템의 사용성 문제 일부를 해결하려는 여러 관련 제안을 기각합니다.

여기에는 다음이 포함됩니다.

  • 안전하게 외부에서 호스팅되는 파일은 기본적으로 허용하되, 안전하지 않게 호스팅되는 파일은 허용하지 않는 방안.
  • 안전하게 외부 호스팅된 파일은 기본적으로 허용하지 않되 전역 플래그 하나로만 허용할 수 있게 하고, 안전하지 않게 호스팅된 파일은 허용하지 않습니다.
  • PEP 438이 제안한 방향을 계속 따라, 안전하지 않은 외부 호스팅 옵션은 제거하고 안전한 외부 호스팅 옵션은 계속 허용합니다.

이 제안들은 다음과 같은 이유로 거부되었습니다.

  • PEP 438에서 도입한 분류 체계는 PyPI에만 있는 완전히 고유한 개념으로, Python 패키징 맥락에서조차 일반적으로 적용할 수 없습니다. 개념을 추가하는 데에는 비용이 따릅니다.
  • 분류 체계 자체가 설명하기 쉽지 않으며, 프로젝트에 어떤 분류의 링크가 필요할지 미리 판단하려면 프로젝트의 /simple/<project>/ 페이지와, 경우에 따라서는 그 페이지에서 링크된 모든 URL까지 살펴보아야 합니다.
  • 외부에 호스팅하면서도 자동 탐색을 위해 링크되도록 하는 기능은 대체로 과거의 유물로, 얻는 것은 적은 데 비해 상당한 고통과 복잡성을 유발합니다.
  • 수행해야 하는 암묵적인 링크 스크레이핑의 특성 때문에, 설치 프로그램이 사용자 인터페이스를 최적화하거나 정리할 수 있는 능력은 제한됩니다. 이는 --allow-* 옵션에도 해당하며, 링크가 실패할 것으로 예상되는지 여부를 판단할 수 없다는 문제에도 해당합니다.
  • 이 메커니즘은 옵션을 활성화할 때 매우 광범위하게 적용되는 반면, PEP 438은 패키지별 옵션으로 이를 제한하려고 합니다. 그러나 오랫동안 존재해 온 프로젝트는 simple 색인에 여러 개의 서로 다른 URL이 나열되어 있는 경우가 많습니다. 이 중 적어도 하나가 더 이상 프로젝트의 통제하에 있지 않은 경우도 드물지 않습니다. 등록되지 않은 도메인은 대부분의 경우 비교적 무해하게 방치되어 있지만, pip는 탐색 단계마다 계속해서 그 도메인에서 설치를 시도합니다. 즉, 공격자는 안전하지 않은 외부 URL에 의존하는 프로젝트를 찾아 만료된 도메인을 등록하기만 하면 사용자를 공격할 수 있습니다.

이 PEP를 구현하되, 기존 링크는 제거하지 않기

이는 본질적으로 이 PEP의 하위 호환 버전입니다. 이 방안은 구버전 클라이언트나 이 PEP를 구현하지 않은 클라이언트를 사용하는 사람들이 아무것도 바뀌지 않은 것처럼 계속 사용할 수 있도록 하려는 것입니다. 이러한 시나리오의 대부분이 폐기 예정 기능을 안전하지 않게 사용하는 경우이므로, 이 제안은 거부되었습니다. 이 PEP는 최종 사용자를 대신하여 안전하지 않은 동작이 조용히 일어나도록 허용하는 것은 결코 받아들일 수 있는 해결책이 아니라고 봅니다.