[Superseded] PEP 438 - Transitioning to release-file hosting on PyPI
원문 링크: PEP 438 - Transitioning to release-file hosting on PyPI
상태: Superseded 유형: Process 작성일: 15-Mar-2013
PEP 438 – PyPI에서 릴리스 파일 호스팅으로의 전환
개요 (Abstract)
이 PEP(Python Enhancement Proposal)는 pypi.python.org
(PyPI) 패키지 인덱스에서 패키지를 설치하는 과정을 더 빠르고, 간단하며, 견고하게 만들기 위한 하위 호환성을 유지하는 2단계 전환 프로세스를 제안합니다. 전환을 원활하게 하고 클라이언트 측의 마찰을 최소화하기 위해, 첫 번째 전환 단계의 이점을 얻기 위해 distutils
나 기존 설치 도구를 변경할 필요는 없습니다. 이는 대부분의 기존 패키지에 대해 더 빠르고 안정적인 설치를 제공할 것입니다.
첫 번째 전환 단계에서는 패키지 관리자가 현재의 설치 도구에 제공되는 릴리스 파일 링크를 제어할 수 있는 쉽고 명시적인 방법을 구현합니다. 또한, 현재 패키지에 대한 분석 도구 구현을 포함하여 패키지 관리자와의 소통 및 릴리스 파일 링크 제어를 위한 기본 모드 자동 설정을 지원합니다. 새로운 프로젝트는 기본적으로 PyPI에 업로드된 릴리스 파일에 대한 링크만 제공하도록 설정될 것입니다.
두 번째 전환 단계는 최종 사용자 설치 도구에 관한 것으로, 기본적으로 PyPI에 호스팅된 릴리스 파일만 설치하고 외부 릴리스 파일이 존재할 경우 사용자에게 알린 후, 해당 외부 파일을 자동으로 사용할지 선택할 수 있는 옵션을 제공합니다. 미래에는 외부 릴리스 파일이 체크섬 해시와 함께 등록되어 설치 도구가 다운로드의 무결성을 검증할 수 있도록 할 것입니다 (PyPI에 호스팅된 릴리스 파일은 항상 체크섬을 가집니다).
대체 PyPI 서버 구현은 전환 1단계의 새로운 간단한 인덱스 제공 동작을 구현해야 합니다. 이는 2단계에서 설치 도구가 해당 릴리스 링크를 외부 링크로 처리하는 것을 방지하기 위함입니다.
배경 (Rationale)
외부 호스팅의 역사 및 동기 (History and motivations for external hosting)
PyPI가 처음 시작되었을 때, 릴리스 등록은 제공했지만 릴리스 파일을 직접 호스팅하는 기능은 없었습니다. 호스팅 기능이 추가되었을 때도 자동 다운로드 도구는 아직 존재하지 않았습니다. Phillip Eby가 setuptools
를 통해 자동 다운로드를 구현했을 때, 사용자가 원하는 다운로드 호스트를 사용할 수 있도록 허용하는 선택을 했습니다. 외부 호스팅 패키지를 찾는 방법은 다음과 같이 구현되었습니다:
패키지의 PyPI simple/
인덱스는 해당 릴리스의 long_description
메타데이터에서 스크랩한 모든 링크를 포함합니다. “Download-URL” 및 “Home-page” 메타데이터 필드의 링크에는 각각 rel=download
및 rel=homepage
속성이 부여됩니다. 이러한 링크 중 “packagename-version.ARCHIVEEXT” 형식의 설치 가능한 소스 또는 바이너리 배포판으로 보이는 파일을 대상으로 하는 링크는 설치 도구에 의해 잠재적인 설치 후보로 간주됩니다. 마찬가지로, “#egg=packagename-version” 조각(fragment)이 붙은 링크도 설치 후보로 간주됩니다. 또한, rel=homepage
및 rel=download
링크는 설치 도구에 의해 크롤링되며, HTML인 경우 위에서 언급한 형식의 릴리스 파일 링크를 스크랩합니다.
이 동작에 대한 완전한 설명은 easy_install
문서를 참조하세요.
오늘날 PyPI에 인덱싱된 대부분의 패키지는 릴리스 파일을 PyPI에 직접 호스팅합니다. 전체 29,117개 PyPI 프로젝트 중 2,581개(10% 미만)만이 PyPI 외부에서만 사용 가능한 설치 가능한 파일에 대한 링크를 포함하고 있습니다.
사람들이 외부 호스팅을 선택한 데에는 여러 가지 이유가 있습니다. 몇 가지 예시를 들자면 다음과 같습니다:
- 릴리스 프로세스 및 스크립트가 이미 개발되어 외부 사이트에 업로드하고 있음.
- 일부 지역에서는 대용량 파일을 업로드하는 데 너무 오랜 시간이 걸림.
- 암호화 관련 소프트웨어에 대한 수출 제한.
- 자사 사이트를 통해 오픈 소스 패키지를 제공해야 하는 회사 정책.
- PyPI 업로드를 릴리스 프로세스에 통합하는 데 문제 발생 (릴리스 정책으로 인해).
- PyPI에서 유지 관리하는 다운로드 통계와 다른 다운로드 통계를 원함.
- PyPI의 신뢰성이 낮다고 인식함.
- PyPI가 파일 호스팅을 제공한다는 사실을 인지하지 못함.
이러한 이유들의 현재 유효성 여부와 관계없이, 사람들이 파일을 외부에서 호스팅하도록 선택한 역사적인 배경이 분명히 있으며, 한동안은 그렇게 하는 것이 유일한 방법이었습니다. 이 PEP는 오늘날에도 외부 호스팅에 대한 일부 유효한 이유가 남아있다는 입장을 취합니다.
문제 (Problem)
오늘날 Python 패키지 설치 프로그램(pip, easy_install, buildout 등)은 외부에서 호스팅되는 파일이 없더라도 많은 PyPI 외부 URL을 쿼리해야 하는 경우가 많습니다. pypi.python.org
의 simple/
인덱스 페이지를 쿼리하는 것 외에도, 패키지의 모든 릴리스에서 지정된 모든 홈페이지 및 다운로드 페이지도 설치 프로그램에 의해 크롤링됩니다. 설치 프로그램이 외부 사이트를 크롤링해야 하는 필요성 때문에 설치 속도가 느려지고, 설치 프로세스가 취약하며 신뢰할 수 없게 됩니다. 이러한 사이트와 패키지는 PEP 381 미러링 인프라에 참여하지 않아 전 세계 자동 설치 프로세스의 신뢰성과 속도를 더욱 떨어뜨립니다.
대부분의 패키지는 pypi.python.org
에 직접 호스팅됩니다. 이러한 패키지의 경우에도, 홈페이지 및 다운로드 URL이 지정되어 있으면 설치 프로그램이 여전히 해당 페이지를 크롤링합니다. 많은 패키지 업로더는 패키지 메타데이터에 “homepage” 또는 “download-url”을 지정하는 것이 모든 사용자의 설치 프로세스를 불필요하게 늦춘다는 사실을 알지 못합니다.
타사 사이트에 의존하는 것은 자동 설치를 사용하는 사이트에 악성 패키지를 주입하기 위한 더 많은 공격 벡터를 열어줍니다. 간단한 공격은 오래되고 현재 사용되지 않는 홈페이지 도메인을 확보하고 거기에 악성 패키지를 배치하는 것일 수 있습니다. 또한, 설치 사이트와 다운로드 사이트 간의 Man-in-The-Middle (MITM) 공격을 수행하면 설치 사이트에 악성 패키지를 주입할 수 있습니다. 많은 홈페이지 및 다운로드 위치가 HTTPS가 아닌 HTTP를 사용하고 있으므로 이러한 공격은 쉽게 시작될 수 있습니다. 이러한 MITM 공격은 파일을 외부에서 호스팅할 의도가 전혀 없었던 패키지의 경우에도 설치 프로그램이 해당 홈페이지에 접속하기 때문에 쉽게 발생할 수 있습니다.
현재 패키지 관리자가 외부 링크 크롤링을 피할 수 있는 방법은 모든 과거 릴리스에 대한 모든 홈페이지/다운로드 URL 메타데이터를 제거하는 것 외에는 없습니다. 이 작업을 수행하는 스크립트가 작성되었지만, PyPI 릴리스에서 유용한 메타데이터를 제거하기 때문에 좋은 일반적인 해결책은 아닙니다.
“Homepage” 및 “Download-URL” 링크에서 참조된 사이트가 추가 링크를 위해 스크랩되지 않더라도, 현재 시스템에서는 패키지 소유자가 long_description
메타데이터 필드( /pypi/PKG
에 패키지 문서로 표시됨)에서 설치 가능한 파일에 연결하는 명확한 방법이 없으며, 설치 도구가 해당 파일을 자동으로 설치 후보로 간주하지 않도록 할 방법도 없습니다. 반대로, 메타데이터 필드에 넣지 않고 여러 외부 릴리스 파일을 명시적으로 등록할 방법도 없습니다.
목표 (Goals)
이 PEP 구현을 통해 달성하고자 하는 목표는 다음과 같습니다:
- 패키지 소유자는 PyPI가 설치 도구에 설치 후보로 제시하는 파일을 명시적으로 제어할 수 있어야 합니다.
- 패키지 소유자가 명시적으로 설치 파일로 지정하지 않은 링크를 광범위하고 불필요하게 크롤링하여 설치가 느려지거나 신뢰성이 떨어지는 일이 없어야 합니다.
- 패키지 소유자가 릴리스 파일을 PyPI 외부의 자체 호스팅에서 호스팅하도록 선택할 수 있어야 합니다.
- 사용자가 자동 설치 도구를 사용하여 이러한 릴리스를 설치하도록 요청하는 것이 쉬워야 합니다. 특히 외부 릴리스 파일이 체크섬 해시와 함께 등록된 경우 더욱 그렇습니다.
- 자동 설치 도구는 기본적으로 외부 호스팅 패키지를 설치해서는 안 되며, 사용자로부터 명시적인 권한을 요구해야 합니다.
- 도구가 기본적으로 그러한 패키지 설치를 거부할 때, 사용자에게 설치 프로그램이 따라야 할 정확한 외부 링크와 해당 링크를 따르도록 도구에 권한을 부여하기 위해 사용자가 제공할 수 있는 옵션을 정확히 알려주어야 합니다.
- PyPI는 설치 도구가 이를 쉽게 구현하고 단일 요청/응답 상호 작용 내에서 구현하는 데 필요한 모든 메타데이터를 제공해야 합니다.
- 현재 상태에서 위의 요점으로의 마이그레이션은 점진적이어야 하며, 시스템 오류를 최소화해야 합니다. 여기에는 기존 릴리스 프로세스가 PyPI 이외의 호스팅에 업로드하는 패키지 소유자가 해당 릴리스 파일을 PyPI에도 쉽게 업로드할 수 있도록 하는 도구가 포함됩니다.
해결책 / 두 가지 전환 단계 (Solution / two transition phases)
첫 번째 전환 단계는 PyPI의 각 프로젝트에 “호스팅 모드(hosting-mode)” 필드를 도입하여, 패키지 소유자가 기계가 읽을 수 있는 simple/
인덱스에서 현재 설치 도구에 제공되는 릴리스 파일 링크를 명시적으로 제어할 수 있도록 합니다. 초기 적용자들이 호스팅 모드를 성공적으로 조작한 후, 첫 번째 전환은 자동 분석을 기반으로 기존 패키지에 대한 기본 호스팅 모드를 설정할 것입니다. 관리자에게는 이러한 자동 변경에 대해 한 달 전에 통지될 것입니다. 첫 번째 전환 단계가 완료되면, 현재의 모든 기존 릴리스 및 설치 프로세스와 도구는 계속 작동할 것으로 예상됩니다. 남아있는 오류나 문제는 개별 패키지 설치와만 관련될 것으로 예상되며, 관리자가 연락 불가능한 경우 패키지 관리자 또는 PyPI 관리자가 쉽게 수정할 수 있습니다.
또한 첫 번째 단계에서는 simple/
인덱스에 제공되는 각 링크가 인덱스 자체에 호스팅된 경우(CDN
을 사용하는 경우에도 해당) rel="internal"
로 명시적으로 표시됩니다. 이렇게 표시되지 않은 모든 링크는 외부 링크로 간주됩니다.
두 번째 전환 단계에서는 PyPI 클라이언트 설치 도구가 업데이트되어 사용자가 외부 링크에서 설치를 허용하는 옵션을 지정하지 않는 한 기본적으로 rel="internal"
패키지만 설치하도록 변경될 것입니다. 설치 프로그램이 어떻게 동작해야 하는지에 대한 자세한 내용은 두 번째 전환 단계를 참조하십시오.
현재 PyPI 이외의 사이트에 릴리스 파일을 호스팅하는 패키지의 관리자는 과거 및 미래 패키지 릴리스 파일을 “재호스팅(re-hosting)”하는 데 도움이 되는 지침과 도구를 받게 될 것입니다. 이 재호스팅 도구는 패키지 관리자에게 자동 호스팅 모드 변경이 발표되기 전에 사용 가능해야 합니다.
구현 (Implementation)
호스팅 모드 (Hosting modes)
첫 번째 전환 단계의 기반은 PyPI 호스팅에 세 가지 “모드”를 도입하는 것으로, 이는 simple/
인덱스에 생성되는 링크에 영향을 미칩니다. 이 모드는 기계가 읽을 수 있는 simple/
인덱스 생성 알고리즘 변경을 통해 설치 도구 변경 없이 구현됩니다.
모드는 다음과 같습니다:
pypi-scrape-crawl
: 설치 도구를 위한 기계가 읽을 수 있는 링크를 생성하는 현재 상황과 동일하며, 역사 섹션에 설명된 바와 같습니다.pypi-scrape
: 이 모드의 패키지의 경우,simple/
인덱스에 추가될 링크는 여전히 패키지 메타데이터에서 스크랩됩니다. 그러나 “Home-page” 및 “Download-url” 링크에는rel=homepage
및rel=download
속성 대신rel=ext-homepage
및rel=ext-download
속성이 부여됩니다. (설치 도구 변경 없이) 이로 인한 효과는 이러한 링크가 현재의 설치 도구에 의해 추가 후보 링크를 위해 추적되고 스크랩되지 않는다는 것입니다. 즉, PyPI에서 직접 호스팅되거나 PyPI 메타데이터에서 직접 연결된 설치 가능한 파일만 설치 대상으로 고려됩니다. 설치 도구는 새로운rel
속성을 사용하여 외부 페이지를 크롤링하는 옵션을 제공하도록 발전할 수 있지만, 기본적으로 그렇게 해서는 안 됩니다.pypi-explicit
: 이 모드의 패키지의 경우, PyPI에 업로드된 릴리스 파일에 대한 링크와 패키지 소유자가 명시적으로 지정한 외부 릴리스 파일에 대한 링크만simple/
인덱스에 추가됩니다. PyPI는 패키지 소유자가 외부 릴리스 파일 URL을 제공할 수 있는 새로운 인터페이스를 제공할 것입니다. 이러한 URL에는 다운로드한 파일의 무결성을 검증하기 위해 설치 도구가 사용해야 하는 해시를 지정하는 “#hashtype=hashvalue” 형식의 URL 조각(fragment)이 반드시 포함되어야 합니다.
따라서, 결국 PyPI의 모든 프로젝트가 pypi-explicit
모드로 마이그레이션될 수 있기를 바라며, 설치 도구를 통해 외부에서 호스팅되는 릴리스 파일을 설치할 수 있는 기능을 유지하는 것을 목표로 합니다. pypi-explicit
모드만 허용하도록 호스팅 모드를 최종적으로 폐지하는 것은 이 PEP에 의해 규제되지 않지만, 이 PEP에 설명된 전환 단계의 성공적인 구현 이후 어느 시점에서 가능해질 것으로 예상됩니다. 폐기에는 여전히 인기 있는 패키지의 연락 불가능한 관리자로 인해 버려진 패키지를 처리하기 위한 새로운 프로세스가 필요할 것으로 예상됩니다.
첫 번째 전환 단계 (PyPI) (First transition phase (PyPI))
제안된 해결책은 여러 구현 및 통신 단계로 구성됩니다:
- 위에 설명된 세 가지 모드를 PyPI에 구현하고, 패키지 소유자가 각 패키지에 대한 모드를 선택하고 명시적인 외부 파일 URL을 등록할 수 있는 인터페이스를 제공합니다.
- 모든 모드의 패키지에 대해
simple/
인덱스에서 인덱스 호스팅 파일에 대한 링크를rel="internal"
로 레이블링하여 클라이언트 도구가 두 번째 단계에서 이러한 링크를 더 쉽게 구별할 수 있도록 합니다. - 모든
simple/
인덱스 페이지에<meta name="api-version" value="2">
HTML 태그를 추가하여 클라이언트가rel="internal"
메타데이터를 제공하는 인덱스와 그렇지 않은 이전 인덱스를 구별할 수 있도록 합니다. - 새로 등록되는 모든 패키지의 기본 모드를
pypi-explicit
모드로 설정합니다 (패키지 소유자는 원하는 경우 다른 모드로 전환할 수 있습니다). - 자동 분석을 통해 모든 설치 가능한 파일이 PyPI 자체에서 사용 가능한 패키지(그룹 A), 모든 설치 가능한 파일이 PyPI에 있거나 PyPI 메타데이터에서 직접 연결된 패키지(그룹 B), 그리고 외부 홈페이지/다운로드 HTML 페이지에서만 연결된 설치 가능한 버전이 있는 패키지(그룹 C)를 결정합니다.
- 그룹 A 프로젝트의 관리자에게는 한 달 내에 프로젝트가 자동으로
pypi-explicit
모드로 구성될 것임을 메일로 알리고, 그룹 B 프로젝트의 관리자에게는 프로젝트가 자동으로pypi-scrape
모드로 구성될 것임을 알립니다. 이 변경이 프로젝트의 설치 가능성에는 전혀 영향을 미치지 않지만, 사용자에게는 더 빠르고 안전한 설치를 제공할 것이라고 알립니다. 사용자에게 혜택을 주기 위해 이 모드를 더 빨리 직접 설정하도록 권장합니다. - 그룹 C 패키지의 관리자에게는 패키지 호스팅 모드가
pypi-scrape-crawl
임을 알리고, 현재 크롤링되는 URL을 나열하며, PyPI에 직접 패키지를 재호스팅하고pypi-explicit
으로 전환하거나, 최소한 PyPI 메타데이터에 릴리스 파일에 대한 직접 링크를 제공하고pypi-scrape
로 전환하도록 제안합니다. 이러한 전환을 돕기 위한 지침과 도구를 제공합니다.
두 번째 전환 단계 (설치 도구) (Second transition phase (installer tools))
두 번째 전환 단계에서는 설치 도구 관리자에게 두 가지 업데이트를 릴리스하도록 요청합니다.
첫 번째 업데이트는 외부 호스팅 릴리스 파일(즉, rel="internal"
이 포함되지 않은 링크를 가진 파일)이 다운로드 대상으로 선택될 경우 명확한 경고를 제공하고, 어떤 프로젝트와 URL에서 이러한 일이 발생하는지 정확히 알려주며, 향후 버전에서는 외부 호스팅 다운로드가 기본적으로 비활성화될 것이라고 경고해야 합니다.
두 번째 업데이트는 기본 모드를 rel="internal"
패키지 파일만 설치하도록 변경하고, 사용자가 옵션을 제공하는 경우에만 외부 호스팅 패키지 설치를 허용해야 합니다.
설치 프로그램은 검증 가능한 외부 링크와 검증 불가능한 외부 링크를 구별해야 합니다. 검증 가능한 외부 링크는 다운로드된 파일의 무결성을 검증하는 데 사용할 수 있는 해시가 URL 조각(“#hashtype=hashvalue”)에 포함된 PyPI simple/
인덱스에서 설치 가능한 파일에 대한 직접 링크입니다. 검증 불가능한 외부 링크는 해시가 없거나, 외부 HTML에서 스크랩되거나, 다른 PyPI 이외의 소스(예: setuptools
의 dependency_links
기능)를 통해 검색에 주입된 모든 링크(설치 도구의 사용자가 명시적으로 제공한 링크 제외)입니다.
설치 프로그램은 모든 검증 가능한 외부 링크 설치를 허용하는 포괄적인 옵션을 제공해야 합니다. 검증 불가능한 외부 링크는 사용자가 제공한 옵션이 사용할 수 있는 정확한 외부 도메인 또는 특정 패키지 이름에 대해 외부 링크를 사용할 수 있다고 지정하는 경우에만 설치되어야 합니다.
기본 구성으로 인해 외부 호스팅 패키지 다운로드가 허용되지 않는 경우, 사용자에게 설치 성공 방법 및 그 의미(파일이 패키지 인덱스의 일부가 아닌 사이트에서 다운로드될 것임)에 대한 경고와 함께 통지해야 합니다. 검증 불가능한 링크에 대한 경고는 설치 프로그램이 다운로드된 파일의 무결성을 검증할 수 없음을 명확히 명시해야 합니다. 검증 가능한 외부 링크에 대한 경고는 파일이 외부 URL에서 다운로드될 것이지만 파일 무결성은 체크섬으로 검증될 수 있음을 단순히 언급해야 합니다.
대체 PyPI 호환 인덱스 구현은 가능한 한 빨리 rel="internal"
메타데이터와 <meta name="api-version" value="2">
태그를 제공하도록 업그레이드해야 합니다. simple/
페이지에 아직 메타 태그를 제공하지 않는 대체 인덱스의 경우, 설치 도구는 하위 호환 가능한 대체 동작(PEP 이전처럼 링크를 내부로 처리하고 경고 제공)을 제공해야 합니다.
외부 배포 URL 제출을 위한 API (API For Submitting External Distribution URLs)
새로운 배포 URL은 다음 URL로 HTTP POST를 수행하여 제출할 수 있습니다:
https://pypi.python.org/pypi
다음과 같은 폼 인코딩된 데이터를 포함해야 합니다:
이름 (Name) | 값 (Value) |
---|---|
:action |
문자열 “urls” |
name |
패키지 이름 (문자열) |
version |
릴리스 버전 (문자열) |
new-url |
저장할 새 URL |
submit_new_url |
문자열 “yes” |
POST 요청에는 PyPI에서 패키지를 유지 관리할 권한이 있는 사용자의 사용자 이름과 암호를 인코딩하는 HTTP Basic Auth 헤더가 동반되어야 합니다.
이 요청에 대한 HTTP 응답은 다음 중 하나가 될 것입니다:
코드 (Code) | 의미 (Meaning) | URL 제출 관련 (URL submission implications) |
---|---|---|
200 |
OK |
모든 작업이 정상적으로 수행되었습니다. |
400 |
Bad request |
제출을 위해 제공된 데이터 형식이 잘못되었습니다. |
401 |
Unauthorised |
제공된 사용자 이름 또는 비밀번호가 올바르지 않습니다. |
403 |
Forbidden |
사용자가 패키지 정보를 업데이트할 권한이 없습니다 (소유자 또는 관리자가 아님). |
참조 (References)
- Phillip Eby,
easy_install
‘Package Index “API”’ 문서 - Donald Stufft, PyPI 프로젝트 링크 자동 분석
- Marc-Andre Lemburg, 외부 호스팅 이유
- Holger Krekel, 모든 릴리스에 대한 홈페이지/다운로드 메타데이터 제거 스크립트
감사의 말씀 (Acknowledgments)
- Phillip Eby는 서버 측 변경만으로 전환을 구현하는 데 필요한 정확한 정보와 기본적인 아이디어를 제공했습니다.
- Donald Stufft는 외부 호스팅에서 벗어나기 위해 노력했으며, 필요한 PyPI 변경 사항에 대한 Pull Request와 전환 1단계를 추진하기 위한 분석 도구를 구현할 것을 제안했습니다.
- Marc-Andre Lemburg, Alyssa Coghlan 및 일반적인
catalog-sig
는 “외부 호스팅” 제거와 관련된 문제를 깊이 있게 고민해 주었습니다.
저작권 (Copyright)
이 문서는 퍼블릭 도메인에 공개되었습니다.
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments