PEP 605 – CPython을 위한 순환 기능 릴리스 스트림
- Author:
- Steve Dower <steve.dower at python.org>, Alyssa Coghlan <ncoghlan at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Rejected
- Type:
- Informational
- Created:
- 20-Sep-2019
- Python-Version:
- 3.9
- Post-History:
- 01-Oct-2019, 06-Oct-2019, 20-Oct-2019
Table of Contents
- 거부 통지
- 초록
- 향후 릴리스 일정 예시
- 향후 릴리스 공지 예시
- 동기
- 이 제안의 목표
- 제안
- 주의 사항 및 제한 사항
- 설계 논의
- 단순히 X.Y.0 릴리스를 더 자주 진행하는 대신 롤링 프리-프리즈 릴리스를 사용하는 이유는 무엇입니까?
- “alpha” 및 “beta” 명명 체계를 유지해야 합니까?
- 안정 릴리스 시리즈와 불안정 릴리스 시리즈를 번갈아 사용하는 대신 롤링 프리-프리즈 릴리스를 사용하는 이유는 무엇입니까?
- 롤링 릴리스 스트림에 Calendar Versioning을 사용하지 않는 이유는 무엇입니까?
- 롤링 프리프리즈 릴리스 사용자는 API 변경을 어떻게 감지합니까?
- X.Y.0rc1 이후 재빌드를 강제하기 위해 새로운 프리프리즈 ABI 플래그를 추가하는 이유는 무엇입니까?
- X.Y.0a1 이후에 추가 알파 릴리스를 허용하는 이유는 무엇입니까?
- CPython 핵심 개발에 미치는 영향
- Python 라이브러리 개발에 미치는 영향
- 제안된 Scientific Python 생태계 지원 기간에 미치는 영향
- 핵심 개발 스프린트를 위한 릴리스 주기 정렬
- 주요 Linux 배포판을 위한 릴리스 주기 정렬
- 단순한 배포 환경에 대한 영향
- 복잡한 배포 환경에 대한 영향
- 감사의 말
- 참고 자료
- Copyright
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
거부 통지
이 PEP는 PEP 602를 채택하여 거부되었습니다. 알파/베타 교대 가능성은 너무 혼란스럽고 릴리스 간 2년 주기는 너무 길다고 판단되었습니다.
초록
오랫동안 CPython의 명목상 기능 릴리스 주기는 “18~24개월마다”였으며, 최근 몇 년 동안에는 이 범위의 “18개월” 쪽에 상당히 일관되게 가까웠습니다. PEP 607은 이러한 주기 선택으로 인해 발생하는 문제에 대한 몇 가지 공통 배경과 이를 변경하고자 할 때 고려해야 하는 일부 위험을 설명합니다.
이 PEP의 제안은 CPython 사용자층이 서로 구별되지만 일부 겹치는 다음 두 그룹 중 하나를 스스로 선택할 수 있도록 하는 것을 목표로 합니다.
- 24개월마다 게시되는 안정 기능 릴리스 및 이에 수반되는 유지보수 릴리스 스트림의 사용자
- 기존 CPython 프리릴리스 프로세스를 대신하는 새로운 순환 릴리스 스트림의 얼리 어답터
이 제안의 일환으로 베타 릴리스에 대한 사용 지침은 현재의 무조건적인 “프로덕션에서 사용하지 마십시오” 대신 “충분히 견고한 호환성 테스트 및 운영 모니터링 역량을 갖춘 환경에서만 프로덕션 사용에 적합합니다”로 변경됩니다.
마찬가지로 알파 릴리스에 대한 지침도 단순히 “프로덕션에서 사용하지 마십시오”라고 하는 대신 “라이브러리 호환성 테스트 및 ABI 호환 바이너리 아티팩트 생성에 사용하도록 의도되었습니다”라고 수정됩니다.
PEP 작성자들은 아래 제안 절에서 설명하는 CPython 프리릴리스 관리 프로세스의 수정으로 이러한 결과를 달성할 수 있다고 믿습니다.
또한 이 PEP는 X.Y.0 릴리스의 빈도를 조정하여 2년마다 8월에 새로운 릴리스 시리즈를 시작할 것을 제안합니다(2021년부터 시작하며, Python 3.8.0 릴리스 약 2년 후입니다).
향후 릴리스 일정 예시
이 제안에 따르면 Python 3.9.0a1은 2019년 10월 Python 3.8.0 기준 기능 릴리스가 나온 지 두 달 후인 2019년 12월에 릴리스됩니다.
전체 CPython ABI에 추가적인 호환성 파괴 변경이 이루어지지 않는다고 가정하면, 3.9.0b2 릴리스는 그로부터 2개월 후인 2020년 2월에 이어서 나오며, 2021년 4월의 3.9.0b9까지 계속됩니다.
전체 CPython ABI에 호환성 파괴 변경이 도입될 때마다 이를 포함하는 최초의 프리릴리스는 알파 릴리스로 표시됩니다.
3.9.0rc1은 2021년 6월에, 3.9.0rc2는 2021년 7월에 게시되고, 이후 정식 릴리스가 2021년 8월에 3.9.0으로 게시됩니다.
2021년 10월에 3.10.0a1이 게시되면서 주기가 다시 시작됩니다(3.9.x 유지보수 브랜치가 생성된 지 4개월 후입니다).
유지보수 릴리스의 정확한 일정은 릴리스 팀이 정하지만, 3.9.x 유지보수 릴리스도 격월로 진행된다고 가정하면(3.10.0 베타 릴리스와 시기를 엇갈리게 하여), 전체 릴리스 일정은 다음과 같습니다:
- 2019-12: 3.9.0a1
- 2020-02: 3.9.0b2
- … 격월로 베타(또는 알파) 릴리스
- 2021-04: 3.9.0b9
- 2021-06: 3.9.0rc1 (기능 동결, ABI 동결, pyc 형식 동결)
- 2021-07: 3.9.0rc2
- 2021-08: 3.9.0
- 2021-09: 3.9.1, 3.8.x (최종 3.8.x 바이너리 유지보수 릴리스)
- 2021-10: 3.10.0a1
- 2021-11: 3.9.2
- 2021-12: 3.10.0b2
- … 베타(또는 알파) 릴리스와 유지보수 릴리스가 서로 다른 달에 계속됩니다.
- 2023-04: 3.10.0b10
- 2023-05: 3.9.11
- 2023-06: 3.10.0rc1 (기능 동결, ABI 동결, pyc 형식 동결)
- 2023-07: 3.10.0rc2, 3.9.12
- 2023-08: 3.10.0
- 2023-09: 3.10.1, 3.9.13 (최종 3.9.x 바이너리 유지 관리 릴리스)
- 2023-10: 3.11.0a1
- 2023-12: 3.11.0b2
- … 기타
3.9.0a5 및 3.9.0a7 릴리스에서 전체 CPython ABI에 호환성을 깨는 변경을 도입한 추가 프리릴리스가 2개 있었다고 가정하면, 전체 일정은 다음과 같이 됩니다:
Figure 1. Impact of the pre-release process changes on the calendar.
이 모델에서는 항상 2개 또는 3개의 활성 유지 관리 브랜치가 있으므로, 그 측면에서는 현 상태가 유지됩니다. 가장 큰 차이점은 안정적인 유지 관리 브랜치에 바이너리를 제공하는 것에 더해, 프리프리즈 롤링 릴리스에도 사전 빌드된 바이너리를 제공하도록 배포자에게 권장하기 시작한다는 점입니다.
Figure 2. Testing matrix in the 18-month cadence vs. the 24-month
전체 CPython ABI를 대상으로 하며 프리프리즈 롤링 릴리스에 사전 빌드된 바이너리를 제공하기로 선택한 패키지 배포자는 최소한 3.9.0a1 릴리스 이후에 새 wheel 아카이브를 빌드해야 합니다. 이후 알파 릴리스(예: 예시 일정의 3.9.0a5 또는 3.9.0a7 릴리스) 후에 업데이트된 바이너리를 게시해야 하는지는 해당 배포자가 이후 릴리스의 ABI 변경으로 실제 영향을 받았는지에 따라 달라집니다.
현 상태와 마찬가지로, 최종 릴리스에 사전 빌드된 바이너리를 제공하려는 모든 패키지 배포자는 ABI 동결일 이후에 새 wheel 아카이브를 빌드해야 합니다. 현 상태와 달리 이 날짜는 첫 번째 릴리스 후보가 게시되는 시점으로 명확히 표시되며, 배포자가 최종 릴리스를 준비할 수 있도록 몇 달 전에 발생합니다.
향후 릴리스 공지 예시
이 PEP가 승인되면, 업데이트된 프리릴리스 관리 프로세스를 최종 사용자에게 전달하는 데 사용되는 주요 채널은 Python 3.9 What’s New 문서와 릴리스 공지 자체가 됩니다.
이 절에서는 그러한 목적에 사용할 수 있는 텍스트의 초기 초안을 제공합니다.
제안된 “What’s New in Python 3.9” 항목
다음 하위 절을 Python 3.9 What’s New 문서에 추가한 다음, 각 Python 3.9 알파 및 베타 공지에서 이 하위 절로 연결합니다.
PEP 605: 프리릴리스 관리 프로세스 변경 사항
자세히 설명한 바와 같이, PEP 605에서는 충분히 견고한 통합 테스트 및 운영 모니터링 역량을 갖춘 환경에서 프로덕션 사용에 적합하다고 간주되는 베타 릴리스의 연속적인 시리즈를 생성하도록 사전 릴리스 관리 프로세스를 업데이트했습니다.
이 새로운 롤링 모델에서는 알파 릴리스와 베타 릴리스가 통합된 “프리프리즈” 기간의 일부로 서로 섞여 있으며, 알파 릴리스는 확장 모듈이나 임베딩 애플리케이션을 다시 컴파일해야 할 수 있는 전체 CPython ABI의 변경을 나타내고, 베타 릴리스는 바로 앞의 프리릴리스와 완전한 바이너리 호환성을 나타냅니다.
이전 릴리스와 달리 3.9.0 알파 및 베타 릴리스용 사전 빌드된 바이너리의 게시가 적극 권장됩니다. 전체 CPython ABI가 동결되기 전에 확장 모듈을 빌드하고 로드할 때 새로운 프리릴리스 ABI 플래그(“p”)가 설정되어, 이러한 모든 프리프리즈 확장 모듈 빌드가 동결 이후의 인터프리터 빌드에서 무시되도록 보장하기 때문입니다.
전체 CPython ABI는 3.9.0rc1에서 동결되고 ABI 플래그에서 프리릴리스 플래그가 제거됩니다. 이는 최종 3.9.0 릴리스보다 2개월 전에 발생할 것으로 예상됩니다(정확한 목표 날짜는 PEP 596의 릴리스 일정을 참조하십시오).
애플리케이션 개발자에게 롤링 릴리스 스트림으로 마이그레이션하는 것은 다음 안정 릴리스가 나오기 전에 표준 라이브러리와 참조 인터프리터의 개선 사항을 설계하고 개발하는 데 적극적으로 참여할 기회를 제공합니다. 또한 인터프리터 성능 개선 사항이 안정 릴리스에서 제공되기 최대 1년 또는 그 이상 전에 이를 활용할 기회도 제공합니다.
사전 빌드된 wheel 아카이브를 게시하는 라이브러리 개발자가 3.8 안정 릴리스 시리즈와 함께 3.9.x 롤링 릴리스 스트림을 지원하도록 선택하는 경우, 프로젝트가 이미 순수 Python wheel(py3-none-any로 태그됨) 또는 안정적인 C ABI에 맞춰 빌드된 wheel(cp38-abi3-<platform>로 태그되거나 이전 CPython 3.x 릴리스의 동등한 태그가 지정됨)을 게시하고 있다면 특별한 조치가 필요하지 않습니다. 이와 동일한 wheel 아카이브는 이후의 3.9 안정 릴리스 시리즈에서도 사용할 수 있습니다.
전체 CPython ABI에 맞춰 빌드된 사전 빌드 wheel 아카이브를 게시하는 라이브러리 개발자의 경우, 3.9 안정 릴리스 시리즈용 바이너리는 전체 CPython ABI가 동결된 후에 빌드해야 합니다(즉, 3.9.0rc1 이상을 사용해야 합니다).
이러한 라이브러리의 개발자는 3.9.0a1 릴리스(또는 이후의 베타 릴리스)에 맞춰 빌드하고 그 결과를 일반적인 방식으로 게시하여 롤링 릴리스 스트림 지원을 선택할 수도 있습니다.
이상적인 경우, 이러한 방식으로 빌드된 바이너리는 프리 프리즈 전 마지막 릴리스까지 계속 작동합니다. 그러나 프리 프리즈 기간에 프로젝트가 전체 CPython C ABI의 변경으로 영향을 받는 경우, 해당 인터페이스를 변경한 알파 릴리스에 맞춰 영향을 받은 바이너리를 다시 빌드하는 유지보수 업데이트를 게시해야 합니다. 이러한 경우 프로젝트 메타데이터에 해당하는 Python-Requires 항목을 추가해야 합니다. 예를 들어 프로젝트가 3.9.0a5에 도입된 ABI 변경의 영향을 받는다면, 추가할 Python-Requires항목은 다음과 같습니다.:
Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"
(이 추가 메타데이터는 ABI의 이전 변형을 제공하는 3.9 시리즈의 더 이른 프리릴리스에 업데이트된 버전이 설치되지 않도록 합니다.)
애플리케이션 개발자의 경우, 롤링 릴리스 스트림을 지원하기로 선택한 라이브러리 개발자는 새롭거나 업데이트된 API 설계가 안정 릴리스에서 수년 동안 확정되기 전에 (또는 안정 릴리스 시리즈에 잠정 API로 포함되기 전에) 이에 대한 피드백을 제공할 기회를 얻게 됩니다.
3.9.0a1 릴리스의 발표문 예시
이것은 Python 3.9의 첫 번째 프리뷰 릴리스입니다. 알파 릴리스인 이 버전은 라이브러리 및 애플리케이션 호환성 테스트와 ABI 호환 바이너리 아티팩트 생성에 사용하기 위한 것입니다. 프로덕션 환경에서의 사용은 권장하지 않습니다.
프리릴리스 관리 프로세스의 변경 사항
CPython은 충분히 견고한 통합 테스트 및 운영 모니터링 역량을 갖춘 환경에서 프로덕션에 사용하기에 적합하다고 간주되는 베타 릴리스를 연속적으로 제공하도록 설계된 새로운 프리릴리스 관리 프로세스로 전환했습니다. 자세한 내용은 Python 3.9 What’s New 문서(관련 섹션으로 하이퍼링크됨)를 참조하십시오.
3.8과 비교한 3.9 시리즈의 주요 새로운 기능
Python 3.9의 많은 새로운 기능은 아직 계획 및 작성 중입니다. 이미 구현된 주요 새로운 기능 및 변경 사항은 다음과 같습니다.
- …
- (롤링 릴리스 스트림의 동료 코어 개발자 또는 사용자 여러분, 중요하다고 생각하는 기능이 이 목록에서 누락되어 있다면 <릴리스 관리자>에게 알려 주십시오.)
Python 3.9의 다음 프리릴리스는 3.8.0b2로 예상되며, 현재 2020-02-02로 예정되어 있습니다.
3.9.0b2 릴리스의 발표문 예시
이것은 Python 3.9의 두 번째 프리뷰 릴리스입니다. 베타 릴리스인 이 버전은 이전의 3.9.0a1 릴리스와 완전히 바이너리 호환됩니다. 충분히 견고한 통합 테스트 및 운영 모니터링 역량을 갖춘 환경에서만 프로덕션에 사용하는 것이 권장됩니다.
(구현된 변경 사항과 다음 예상 릴리스가 3.9.0b3이라는 내용을 반영한 3.9.0a1 발표문에 따르는 나머지 내용입니다.)
3.9.0a5(중간 스트림 알파 릴리스)의 발표문 예시
이것은 Python 3.9의 다섯 번째 프리뷰 릴리스입니다. 알파 릴리스인 이 버전은 이전의 3.9.0b4 릴리스와 완전히 바이너리 호환되지 않습니다. 이 릴리스는 라이브러리 및 애플리케이션 호환성 테스트와 ABI 호환 바이너리 아티팩트 생성에 사용하기 위한 것입니다. 프로덕션 환경에서의 사용은 권장하지 않습니다.
3.9.0b4와 3.9.0a5 사이의 전체 CPython ABI 주요 변경 사항
- 새 필드
ob_example가PyObject구조체에 추가됩니다. - 잠정 필드
tp_example가PyTypeObject구조체에서 제거됩니다.
롤링 릴리스 스트림을 지원하며 바이너리 호환성을 복원하기 위해 다시 빌드해야 하는 프로젝트는 업데이트된 릴리스에 다음 메타데이터를 추가해야 합니다.:
Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"
(3.9.0a1 발표에 따른 나머지 내용이며, 구현된 변경 사항과 다음 예정 릴리스가 3.9.0b6인 점을 반영합니다)
3.9.0rc1 예시 발표문
Python 3.9의 첫 번째 릴리스 후보입니다. 릴리스 후보인 이 릴리스는 이제 기능이 완성되었고, 전체 CPython ABI가 동결되었으며, ABI 호환성 플래그에서 사전 릴리스 표시가 제거되었습니다. 충분히 견고한 통합 테스트 및 운영 모니터링 역량을 갖춘 환경에서만 프로덕션에 사용하도록 권장합니다.
최종 3.9.0 릴리스 준비
전체 CPython ABI가 동결되었으므로, 해당 ABI를 대상으로 하는 라이브러리 개발자는 안정적인 3.9.x 시리즈용 바이너리를 빌드하고 게시하는 것이 권장됩니다.
롤링 릴리스 스트림을 대상으로 테스트하지 않았던 애플리케이션 개발자는 릴리스 후보를 대상으로 애플리케이션을 테스트하고, Porting Guide(관련 What’s New 섹션으로 연결되는 하이퍼링크)에 이미 언급되지 않은 호환성 회귀를 보고하는 것이 권장됩니다.
두 번째 릴리스 후보는 2021-07-02에 예정되어 있으며, 이후 최종 3.9.0 릴리스는 2021-08-02에 예정되어 있습니다.
3.8과 비교한 3.9 시리즈의 주요 새 기능
이 릴리스의 주요 새 기능 및 변경 사항은 다음과 같습니다.
- …
- (안녕하세요, 동료 코어 개발자 또는 롤링 릴리스 스트림 사용자 여러분. 중요하다고 생각하는 기능이 이 목록에서 빠져 있다면 <the release manager>에게 알려 주십시오.)
동기
현재의 CPython 사전 릴리스 및 릴리스 관리 프로세스는 자동화된 지속적 통합과 운영 모니터링 시스템이 아직 비교적 미성숙했던 시대에 개발되었습니다. 그 이후 많은 조직이 다른 코드 변경에 수반되는 위험보다 실질적으로 더 큰 위험을 추가하지 않고 새로운 CPython 기능 릴리스를 도입할 수 있는 배포 모델을 채택했습니다. 경량 작업별 애플리케이션 컨테이너와 같은 최신 배포 모델은 CI 파이프라인에서 애플리케이션과 언어 런타임을 결합한 다음, 전체 컨테이너 이미지가 나중에 업데이트된 이미지로 교체될 때까지 이들을 함께 유지하기도 더 쉽게 합니다.
이러한 더 넓은 환경의 변화를 고려하여, PEP 602에서는 CPython 기능 릴리스의 빈도를 18~24개월마다에서 12개월마다로 늘려 Python 표준 라이브러리와 CPython 참조 인터프리터의 기능 제공 지연 시간을 줄일 것을 제안했습니다.
안타깝게도 많은 조직에서 새로운 Python 릴리스를 도입하는 비용은 릴리스의 변경 사항 수가 줄어든다고 해서 자동으로 감소하지 않습니다. 주요 비용은 발견된 문제를 해결하는 데 드는 비용이 아니라 문제를 검색하는 데 드는 비용이기 때문입니다. 이러한 검색에는 소프트웨어 시스템의 수동 테스트, 작성된 자료에 대한 사람의 검토, 그리고 필요한 시간이 Python 버전 간 변경 사항 수가 아니라 기존 시스템의 규모에 따라 증가하는 기타 활동이 포함될 수 있습니다.
서드파티 라이브러리 개발자의 경우 비용은 주로 널리 사용되는 서로 다른 Python 버전의 수와 관련됩니다. 현재 이는 python-dev에서 여전히 적극적으로 유지 관리하는 릴리스와 특정 재배포자가 제공하는 최신 버전인 릴리스의 조합에 따라 영향을 받는 경향이 있습니다. 특히 Debian, Ubuntu LTS 및 RHEL/CentOS 시스템 Python 버전이 개발 대상으로 큰 인기를 얻고 있습니다. 더 많은 Python 버전을 대상으로 테스트하는 기본적인 CI 비용 외에도, 널리 사용되는 변형이 많아지면 결함 보고가 프로젝트 자체의 실제 오류인지 아니면 보고한 사용자의 환경 문제인지 판단하기가 더 어려워질 수 있습니다.
PEP 602에서는 영향을 받는 조직과 프로젝트가 모든 릴리스를 도입하려 하기보다 CPython 릴리스를 두 번 또는 세 번에 한 번씩 도입하는 방식으로 간단히 전환할 것을 제안하지만, 이 경우 실무적 측면(예를 들어 사용자가 정기적으로 릴리스를 건너뛸 것으로 예상한다면 지원 중단 예정 기능이 둘 이상의 릴리스를 포괄해야 함)과 문화적 측면(예를 들어 활성 사용 중인 버전이 많아지면 오픈 소스 라이브러리 유지 관리자가 자신은 사용하지 않는 Python 버전에서만 발생하는 버그 보고를 받을 가능성이 훨씬 커짐) 모두에서 해결해야 할 새로운 문제들이 발생합니다.
PEP 598은 이 PEP의 작성자 중 한 명이 릴리스 시리즈가 기능 완성 상태에 도달할 때까지 해당 시리즈 내에서 하위 호환 가능한 기능을 점진적으로 제공할 수 있는 시맨틱 버저닝 방식의 정책을 채택하여 기능 제공 지연 시간을 줄이기 위한 대안적 방안을 제안한 최초의 시도였습니다. 그러나 이 변형 역시 현재 릴리스 관리 모델에 충분히 만족하는 최종 사용자에게 눈에 보이는 변경 사항을 강요한다는 바람직하지 않은 결과를 초래했습니다.
이 PEP에서는 PEP 598과 PEP 602가 공통적인 결함을 공유한다고 봅니다. 두 PEP는 하나의 릴리스 모델이라는 제약 안에서 매우 다른 두 대상 집단의 요구를 충족하려 하고 있으며, 그 결과 설계 요구 사항이 충돌하고 이러한 요구 사항 사이에서 난처한 절충을 해야 하기 때문입니다. 이 PEP의 제안은 서로 구별되는 두 개의 프로덕션 준비 완료 릴리스 스트림을 만들 것을 제안함으로써 이러한 결함을 피하는 것을 목표로 합니다. 기존 릴리스 스트림은 대부분 그대로 유지하고, 새로운 릴리스 스트림은 기능 제공 지연 시간 단축으로 가장 큰 혜택을 얻을 대상 집단에 맞추는 방식입니다.
이 제안의 목표
이 PEP의 제안은 다음과 같은 핵심 가정에 기반합니다.
- 대다수 Python 사용자는 새로운 언어 및 런타임 수준 기능을 적극적으로 요구하지 않으며, 대신 이전에 사용하던 버전의 지원이 중단되거나, Python 제공자가 기본적으로 더 최신 버전을 제공하도록 전환하거나, 자신에게 관심 있는 변경 사항이 업그레이드를 정당화할 만큼 충분히 누적된 경우에만 업그레이드합니다.
- 새로운 릴리스를 사용하는 많은 사용자에게 새 릴리스를 도입할 때 발생하는 작업의 상당 부분은 언어 수준의 호환성 문제에서 비롯되는 것이 아니라 구성 요소 설치 수준의 호환성 문제, 즉 파일 이름과 설치 경로의 변경에서 비롯됩니다.
- Python 사용자층의 일부는 적어도 특정 사용 사례에서 프로덕션 준비가 완료된 사전 릴리스(Windows Insider 또는 Debian 테스트 빌드와 유사함)를 실행할 의향이 있습니다.
이 PEP의 핵심 제안은 CPython 사전 릴리스 프로세스를 변경하여 정기적인 주기로 점진적 기능 릴리스의 연속 스트림을 생성하고, 그러한 빌드 대부분이 적절히 관리되는 프로덕션 시스템에서 사용하기에 충분한 안정성 수준을 제공하도록 보장하는 것입니다.
이 접근 방식을 채택함으로써, 이 제안은 거의 모든 Python 사용자와 기여자에게 더 나은 결과를 제공하고자 합니다:
- 새로운 점진적 기능 릴리스 스트림의 사용자의 경우, 사전 릴리스 단계를 대상으로 하면 PEP 602에서 제안한 연간 주기보다도 더 낮은 기능 제공 지연 시간을 달성할 수 있습니다;
- 새로운 기능을 개발하는 핵심 개발자의 경우, 사전 릴리스의 빈도와 채택률이 높아지면 사전 릴리스 피드백 주기가 개선될 것입니다;
- 기존 릴리스 스트림의 사용자의 경우, 사전 릴리스 기간 동안 채택률이 높아지고 피드백 주기가 개선되면 최초 X.Y.0 릴리스 시점의 기능 성숙도가 높아질 뿐만 아니라 생태계의 준비 수준도 향상될 것입니다;
- Python 라이브러리 유지 관리자의 경우, 사전 릴리스의 연속 스트림은 현재의 사전 릴리스 관리 프로세스보다 정식 안정 릴리스에 포함되기 전에 설계 문제를 식별하고 해결할 기회를 더 많이 제공할 것으로 기대됩니다; 그리고
- 대체 Python 구현의 개발자의 경우, 사전 릴리스의 연속 스트림은 확장 모듈 작성자가 CPython 전체 ABI에서 Python 안정 ABI로 마이그레이션하도록 추가적인 동기를 제공할 수 있으며, 이는 전체 CPython C API를 에뮬레이트하지 않는 구현과 더 많은 생태계 구성 요소가 호환되도록 하는 데에도 기여할 것입니다.
다만 이 제안의 모든 결과가 더 넓은 Python 생태계의 모든 구성원에게 유익하지는 않을 것이라는 점을 인정합니다:
- Python 라이브러리 유지 관리자의 경우, 이 PEP와 PEP 602는 모두 더 빠른 릴리스 주기를 지원하라는 사용자 압력으로 이어질 가능성이 큽니다. 이 PEP는 어떤 사전 릴리스에 CPython 전체 C ABI에 대한 잠재적으로 호환성을 깨뜨리는 변경 사항이 포함되는지 명확히 표시하여 이를 완화하려고 하며, PEP 602는 정식 릴리스 간 최소 기간을 12개월로 유지하여 이를 완화하려고 하지만, 이러한 단점을 완전히 제거할 수는 없습니다;
- 서드파티 확장 모듈 유지 관리자의 경우, 이 PEP와 PEP 602는 모두 새 버전이 제공되는 즉시 해당 버전에서 작동하는 휠 아카이브를 제공하기 위해 안정 ABI를 지원하기 시작하라는 사용자 압력으로 이어질 가능성이 큽니다. 이것이 종합적으로 부정적인지 여부는 요청이 그들에게 어떻게 제시되는지에 따라 달라집니다(요청이 연속적인 사전 동결 릴리스를 지원하는 데 관심이 있는 개발자가 해당 프로젝트에 정중한 기여의 형태로 제공한다면 긍정적일 수도 있습니다);
- 미리 빌드된 휠 아카이브의 가용성에 의존하는 기존 릴리스 스트림의 일부 사용자의 경우, 12개월마다 새 릴리스를 채택하는 것은 수용 가능한 속도 증가일 수 있지만, 역사적인 18~24개월 주기의 24개월 쪽으로 일관되게 이동하는 것은 최근 릴리스에 사용된 18개월 주기에 비해 바람직하지 않은 속도 감소가 될 것입니다. 이 제안이 이러한 사용자에게 종합적으로 부정적인지 여부는 라이브러리 유지 관리자에게 API와 ABI가 동결될 때까지 기다리기보다 다가오는 안정 릴리스를 사전 동결 기간 전체에 걸쳐 지원하는 것이 가치 있다고 설득할 수 있는지에 따라 달라질 것입니다.
제안
이 PEP에서 제안하는 변경 사항의 대부분은 사전 릴리스 버전의 처리에만 영향을 줍니다. 정식 릴리스 버전에 영향을 미치는 유일한 변경 사항은 릴리스 주기를 변경하자는 제안입니다.
안정 릴리스의 2년 주기
참조 인터프리터와 표준 라이브러리의 최신 버전을 사용하려는 사용자에게 연속적인 사전 동결 릴리스를 제공하는 가운데, 이 PEP는 X.Y.0 릴리스의 빈도를 조정하여 2년마다 8월에 새로운 안정 릴리스를 발행할 것을 제안합니다(2021년부터 시작하며, Python 3.8.0 릴리스 후 약 2년이 되는 시점입니다).
이 변경 사항은 사전 동결 릴리스 기간의 처리 방식에 대해 제안된 변경 사항과는 별개의 것으로 볼 수 있지만, 두 사안이 연결되는 이유는 그러한 사전 릴리스 관리 변경 사항이 없다면 2년 정식 릴리스 주기의 단점이 장점을 아마도 능가하는 반면, 12개월 릴리스 주기에서는 그 반대가 사실이기 때문입니다(즉, 이 PEP에서 제안한 사전 릴리스 관리 변경 사항을 적용하면 12개월 정식 릴리스 주기의 단점이 장점을 능가할 것입니다).
알파 및 베타 단계의 “사전 동결” 단계로의 통합
사전 릴리스의 알파 단계와 베타 단계가 서로 구분되고 순차적으로 진행되는 현재 상태를 유지하는 대신, 이 PEP는 두 단계를 릴리스에 단조롭게 증가하는 일련 번호를 부여하는 하나의 “사전 동결” 단계로 통합할 것을 제안합니다.
서로 구분되는 단계를 나타내는 대신, “알파” 및 “베타”라는 이름은 릴리스에 CPython 전체 C ABI를 변경하는 호환성 파괴 변경 사항이 포함되는지 여부를 나타내게 됩니다:
- “알파” 릴리스는 “ABI 호환성 파괴” 릴리스가 되며, 이전 사전 릴리스에서 CPython 전체 ABI에 맞춰 빌드된 확장 모듈이 반드시 올바르게 로드되지는 않습니다
- “베타” 릴리스는 “바이너리 호환” 릴리스가 되며, 이전 사전 릴리스에서 CPython 전체 ABI에 맞춰 빌드된 확장 모듈이 다음 추가 기준을 준수하는 한 올바르게 로드될 것으로 예상됩니다:
- 해당 모듈은 이전 안정 릴리스 계열 또는 개발 중인 사전 릴리스 계열의 잠정적 또는 비공개 C API 중 이번 베타 릴리스에서 제거되었거나 ABI 호환성이 없는 방식으로 변경된 API를 사용해서는 안 됩니다
- 해당 모듈은 이전 안정 릴리스 계열에서 더 이상 사용되지 않도록 지정되었으며 이번 베타 릴리스에서 제거된 C API를 사용해서는 안 됩니다
사전 동결 단계의 기간 및 주기
새로운 X.Y.0 릴리스를 준비하는 몇 달 동안 매월 릴리스하는 대신, 사전 동결 릴리스는 2개월마다 일관되게 발행됩니다.
이 방식이 적용되지 않는 유일한 경우는 다가오는 X.Y.0 릴리스의 2개월 릴리스 후보 기간입니다(자세한 내용은 아래의 릴리스 후보 절을 참조하십시오). 이는 예정되어 있던 릴리스 중 두 개가 건너뛰어진다는 의미입니다(하나는 첫 번째 릴리스 후보 날짜에 해당하고, 다른 하나는 최종 릴리스 날짜에 해당합니다).
사전 동결 단계는 일반적으로 이전 안정 X.Y.0 릴리스 후 2개월 뒤에 시작될 것으로 예상됩니다.
새로운 릴리스 계열의 첫 번째 사전 동결 릴리스는 항상 X.Y.0a1입니다(동일한 ABI 버전 표식을 사용하는 이전 릴리스가 없어 바이너리 호환성을 판단할 대상이 없기 때문입니다).
사전 동결 릴리스에는 최종 안정 릴리스와의 바이너리 호환성 문제를 방지하기 위해 C ABI 호환성 표식에 추가 플래그가 포함됩니다.
베타 릴리스의 릴리스 정책
이 PEP에서는 베타 릴리스 정책을 다음과 같이 설정할 것을 제안합니다.
- 현재 베타 릴리스와 마찬가지로, 베타 릴리스를 준비하고 공개하기 전에 안정적인 BuildBot 플릿이 정상 상태일 것으로 예상합니다.
- 현재 베타 릴리스와 마찬가지로, 릴리스 관리자는 베타 릴리스를 준비하고 공개하기 전에 미해결 릴리스 차단 이슈를 검토할 것으로 예상합니다.
- 현재 베타 릴리스와 마찬가지로,
abi3안정 C ABI에 추가되는 항목은 해당 안정 ABI 버전이 완전히 폐기될 때까지 해당 ABI의 영구적인 일부가 될 것으로 예상합니다(참고: 현재 안정 ABI 버전을 증가시킬 계획은 없습니다). - 현재 베타 릴리스와 달리, 이 PEP에 따른 베타 릴리스는 다음 X.Y.0 릴리스에 대해 기능이 완성된 것으로 간주되지 않습니다.
- 현재 베타 릴리스와 달리, 마지막 CPython 기능 릴리스 이후 추가된 모든 API(안정 C ABI에 추가된 항목은 제외)는 잠정적인 것으로 간주합니다.
- 현재 베타 릴리스와 달리, 이 PEP에 따른 베타 릴리스는 마스터 개발 브랜치에서 준비하고 공개합니다.
- 현재 알파 또는 베타 릴리스와 달리, 이 PEP에 따른 베타 릴리스는 해당 계열의 바로 앞선 프리릴리스와 완전한 ABI 호환성을 갖추어야 합니다(잠정 API에 대한 변경이나 이전 릴리스 계열에서 사용 중단된 API의 제거는 제외합니다).
알파 릴리스의 릴리스 정책
이 PEP에서는 알파 릴리스 정책을 다음과 같이 설정할 것을 제안합니다.
- 현재 알파 릴리스와 마찬가지로, 알파 릴리스를 준비하고 공개하기 전에 안정적인 BuildBot 플릿이 정상 상태일 것으로 예상합니다.
- 현재 알파 릴리스와 마찬가지로, 릴리스 관리자는 베타 릴리스를 준비하고 공개하기 전에 미해결 릴리스 차단 이슈를 검토할 것으로 예상합니다.
- 현재 알파 릴리스와 달리, 릴리스 관리자는 알파 릴리스에서도 현재 베타 릴리스와 비슷한 수준의 안정성을 목표로 삼을 것으로 예상합니다.
이 PEP에 따르면 베타 릴리스의 기준을 충족하는 릴리스를 공개할 수 없고 릴리스 전에 시간을 조금 더 확보해도 문제가 해결되지 않을 때 알파 릴리스를 공개합니다.
전체 CPython API가 ABI 호환성을 깨뜨리는 방식으로 변경되는 경우(예를 들어 공개 구조체 정의에 필드가 추가되거나 제거되는 경우)가 X.Y.0a1 릴리스를 정의하는 최초의 호환성 태그 이후에 추가 알파 릴리스를 공개하게 되는 가장 유력한 이유일 것으로 예상되지만, 각 릴리스에 대한 결정은 릴리스 관리자에게 달려 있습니다.
릴리스 후보 정책, 단계 기간 및 주기
제안된 알파 및 베타 릴리스 단계의 변경에 따라 릴리스 후보 단계에는 다음과 같은 관련 조정이 이루어집니다.
- 기능 동결, ABI 동결, pyc 파일 형식 동결 및 유지보수 브랜치 생성은 모두 X.Y.0rc1 생성 시점에 해당하게 됩니다(현재는 X.Y.0b1, 마지막 베타 릴리스 및 X.Y.0rc1에 걸쳐 혼합되어 발생합니다).
- X.Y.0 릴리스 후보 기간은 3주에서 2개월로 연장합니다.
- 일반적으로 릴리스 후보는 한 달 간격으로 두 개를 발행하지만, 릴리스 관리자의 재량에 따라 추가 후보를 공개할 수 있습니다.
- 최종 X.Y.0 릴리스는 최종 릴리스 후보 후 1~4주 사이에 이루어집니다(두 번째 릴리스 후보 이후 추가 릴리스 후보가 필요했는지에 따라 달라집니다).
- 최종 X.Y.0 릴리스가 8월 목표일을 넘겨 지연되더라도 후속 릴리스 계열에는 영향을 주지 않으며, 후속 릴리스 계열은 여전히 8월로 예정됩니다(현재로부터 2년보다 약간 짧은 후입니다).
이 조정된 정책은 릴리스 후보에 대해 최종 사용자의 피드백을 받을 시간을 더 제공할 뿐만 아니라, Python 프로젝트 유지관리자가 새로운 안정 릴리스 계열을 위한 사전 빌드 휠 아카이브를 빌드하고 공개할 시간도 추가로 제공하여 X.Y.0 릴리스의 초기 사용자 경험을 크게 개선합니다.
CPython 안정 C ABI 관리 변경 사항
CPython 안정 ABI [5]는 특정 CPython 릴리스에 맞춰 빌드된 바이너리 확장 모듈이 동일한 안정 ABI 버전을 지원하는 향후 CPython 릴리스에서도 계속 작동할 것을 약속합니다(현재 버전은 abi3입니다).
제안된 순차적 사전 동결 릴리스 모델에서는 이 약속이 베타 릴리스에도 적용되도록 확대됩니다. 즉, 예정된 Python 버전의 abi3 안정 ABI에 대한 의도적인 추가 항목이 베타 릴리스에 포함된 후에는 abi3 안정 ABI가 지원되는 동안 향후 릴리스에서 해당 항목을 제거하지 않습니다.
안정 ABI에 대한 추가 항목에 관해 커뮤니티 피드백을 받는 데에는 두 가지 주요 메커니즘을 사용할 수 있습니다.
- 선호되는 메커니즘은 먼저 전체 CPython API에 새로운 API를 추가하고, 최소 하나의 공개된 베타 릴리스에 포함되어 관련 사용자 피드백을 받은 후에만 안정 ABI로 승격하는 것입니다.
- 어떤 이유로 해당 접근 방식을 사용할 수 없는 API의 경우(예: 전체 CPython API를 사용할 수 있을 때는 일부 API 추가가 유용한 목적을 제공하지 않을 수 있음), 개발자는 릴리스 관리자에게 다음 릴리스를 알파 릴리스로 표시해 달라고 요청하고(전체 CPython API에 ABI 변경이 없는 경우에도) 그 방법으로 추가 피드백을 얻으려고 시도할 수 있습니다.
가독성과 사용성을 약간 개선하기 위해, 이 PEP는 각 주요 안정 ABI 버전에 대한 별칭 도입도 제안합니다.:
#define Py_LIMITED_API_3_3 0x03030000
#define Py_LIMITED_API_3_4 0x03040000
#define Py_LIMITED_API_3_5 0x03050000
#define Py_LIMITED_API_3_6 0x03060000
#define Py_LIMITED_API_3_7 0x03070000
#define Py_LIMITED_API_3_8 0x03080000
#define Py_LIMITED_API_3_9 0x03090000
// etc...
이러한 별칭은 대상 ABI 버전을 설정하기 위한 확장 모듈 코드와:
#define Py_LIMITED_API Py_LIMITED_API_3_8
어떤 심볼을 사용할 수 있게 해야 하는지 확인하기 위한 CPython 인터프리터 구현 모두에서 사용됩니다.:
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= Py_LIMITED_API_3_9
// A Python 3.9+ addition to the stable ABI would appear here
#endif
롤링 프리 프리즈 릴리스와 안정 C ABI에 대한 문서에서는 이후 프리 프리즈 릴리스의 안정 ABI를 기준으로 빌드된 확장 모듈이 이전 프리 프리즈 릴리스에서 올바르게 로드되지 않을 수 있음을 명확히 설명합니다.
알파 릴리스와 안정 C ABI에 대한 문서에서는 두 알파 릴리스가 연이어 공개되는 경우 알파 릴리스의 안정 ABI를 기준으로 빌드된 확장 모듈조차 다음 릴리스에서 올바르게 로드되지 않을 수 있음을 명확히 설명합니다(이러한 상황은 이상적으로 드물어야 합니다).
전체 CPython ABI 관리 변경 사항
이 PEP는 전체 CPython ABI 관리에 대해 두 가지 변경 사항을 제안합니다.
ABI 호환성을 깨뜨리는 변경 사항을 표시하기 위한 명시적인 커밋 및 NEWS 파일 규칙
이 PEP의 제안에서는 릴리스 관리자가 프리 프리즈 릴리스에 ABI 호환성을 깨뜨리는 변경 사항이 포함되었는지에 따라 해당 릴리스를 알파 릴리스 또는 베타 릴리스로 적절히 표시할 수 있어야 합니다.
이 과정을 지원하기 위해, 핵심 개발자는 전체 CPython C ABI에 호환성을 깨뜨리는 변경 사항을 도입하는 변경의 모든 NEWS 파일 조각 시작 부분에 “(CPython ABI break)” 표시를 포함하도록 요청받습니다.
“CPython” 표시는 이러한 주석이 안정 ABI가 아니라 전체 CPython ABI와 관련된 것임을 명확히 하기 위해 포함됩니다.
커밋 메시지에서는 더 짧은 “(ABI break)” 표시를 커밋 요약 줄의 시작 부분에 배치합니다.
프리 머지 봇은 ABI 호환성 중단 표시가 두 위치 중 하나에 나타나면 양쪽 모두에 나타나도록 업데이트됩니다.
초기 커밋 메시지와 NEWS 항목에서 표시가 실수로 누락된 경우에는 NEWS 항목에 표시를 추가하는 후속 커밋에 커밋 메시지 표시를 포함해야 합니다.
이러한 표시는 릴리스 관리자에게 유용할 뿐만 아니라, 영향을 받는 릴리스에서 테스트할 때 예기치 않은 세그멘테이션 오류를 조사하는 개발자에게도 유용합니다.
프리 프리즈 ABI를 기준으로 빌드했음을 명시적으로 표시하기
전체 CPython ABI는 ABI가 동결되었다고 선언된 후에는 릴리스 계열 내에서만 바이너리 호환성이 적용되고, 서로 다른 릴리스 계열 간에는 소스 호환성만 적용된다는 정책을 오랫동안 따라왔습니다.
이 정책에 따르면 해당 릴리스 계열의 ABI가 동결되기 전에 CPython 프리 릴리스를 기준으로 빌드된 확장 모듈은 최종 릴리스에서 실제로 올바르게 로드되지 않을 수 있습니다.
이는 확장 모듈이 이후 알파 또는 베타 릴리스에서 변경되거나 제거된 잠정적 인터페이스 또는 이전에 사용 중단된 인터페이스에 의존하고 있을 수 있기 때문이며, 확장 모듈에서 사용하는 공개 구조체가 새 필드 추가로 인해 크기가 변경되었기 때문일 수도 있습니다.
역사적으로 알파 및 베타 릴리스의 채택률은 실제 사용에서 문제가 되지 않을 만큼 낮았습니다. 그러나 이 PEP는 베타 릴리스의 광범위한 운영상 사용을 적극적으로 장려할 것을 제안하므로, 해당 릴리스를 사용하는 사용자가 릴리스 후보 및 최종 릴리스를 실행하는 사용자에게 세그멘테이션 오류를 일으키는 바이너리 확장 모듈을 실수로 게시하지 않도록 보장하는 것이 바람직합니다.
이를 위해 이 PEP는 Windows가 아닌 시스템에서 확장 모듈 SOABI마커를 수정하여 CPython 프리 릴리스에 새로운 “p” 플래그를 포함하고, 해당 X.Y.0 버전의 ABI가 릴리스 후보 단계 진입 시 동결된 후에만 이 플래그를 생략하는 방식으로 되돌릴 것을 제안합니다.
이 변경에 따라 3.9.0의 알파 및 베타 릴리스에는 cpython-39p라는 SOABI 태그가 부여되고, 모든 릴리스 후보 및 최종 빌드(3.9.0과 이후 3.9.x 릴리스 모두)에는 수식어가 없는 cpython-39라는 SOABI 태그가 부여됩니다.
디버그 빌드에는 여전히 태그 끝에 “d”가 추가되므로, 프리 릴리스의 디버그 빌드에는 cpython-39pd가 부여됩니다.
Windows 시스템에서 프리 릴리스 빌드의 태그가 지정된 pyd파일 접미사에는 버전 번호 바로 뒤에 프리 릴리스 표시로 “p”가 포함되므로, “cp39p-win_amd64”와 같은 표시가 부여됩니다.
이 변경에 대한 제안된 참조 구현은 [4] 에서 확인할 수 있습니다(참고: 작성 시점에는 해당 구현이 Windows에서 아직 테스트되지 않았습니다).
전체 C ABI 변경의 영향을 받는 프로젝트를 위한 Python-Requires 업데이트
프로젝트가 롤링 프리 프리즈 릴리스 계열에 대한 사전 빌드 바이너리 휠 제공을 처음 선택할 때는 특별히 수행할 작업이 없습니다. 전체 CPython ABI가 해당 릴리스 계열에서 동결된 후 사전 빌드 바이너리 휠을 제공할 때와 마찬가지로 빌드 및 테스트 매트릭스에 롤링 릴리스 계열을 추가하고, 해당 릴리스 계열과 호환되는 것으로 표시된 바이너리 아카이브를 게시하면 됩니다.
그러나 롤링 릴리스 스트림에서 프로젝트가 CPython ABI 호환성 중단의 영향을 받는 경우에는 새 바이너리 빌드와 새로운 환경 제약 Python-Requires마커를 모두 포함하는 버전 업데이트를 릴리스해야 합니다.
예를 들어 롤링 릴리스 스트림을 지원하는 프로젝트가 3.9.0a5 릴리스에서 CPython ABI 호환성 중단의 영향을 받았다면, 업데이트된 바이너리 빌드를 게시한 버전에 다음 메타데이터 항목을 추가합니다.:
Python-Requires: >= "3.9.0b6"; python_version == "3.9" and full_python_version != "3.9.0a5"
이 작업은 게시된 패키지의 일부로 추가 호환성 제약을 추가하므로, 3.9.0b6 이전의 Python 3.9.0 베타 버전은 업데이트된 패키지를 설치 후보로 간주하지 않으며, 해당 패키지를 고려하는 유일한 알파 릴리스는 3.9.0a5 자체입니다.
주의 사항 및 제한 사항
실제 출시 날짜는 출시 팀의 가용성과 다른 행사(예: PyCon US 또는 연례 핵심 개발자 스프린트)의 일정에 따라 릴리스 관리자의 재량으로 최대 한 달 앞당겨지거나 늦춰질 수 있습니다. 그러나 이 제안의 목표 중 하나가 일관된 출시 주기를 제공하는 것이므로, 조정은 이상적으로 드물어야 합니다.
하나의 출시 시리즈 내에서 유지보수 출시의 정확한 빈도는 여전히 릴리스 관리자와 바이너리 릴리스 팀의 재량에 달려 있으며, 이 PEP는 프리릴리스와 X.Y.0 릴리스에 대해 예상되는 주기만 제안합니다.
그러나 예시 일정의 편의를 위해 이 PEP는 유지보수 출시가 격월로 이루어지며, 롤링 프리-프리즈 출시와 번갈아 다른 달에 진행된다고 가정합니다.
릴리스 관리자와 Steering Council은 이 PEP의 제안에 포함된 다양한 세부 사항을 수정할 권한도 계속 보유합니다. 가능한 수정 사항은 다음을 포함하지만 이에 국한되지 않습니다.
- 유지보수 브랜치 생성 시점 변경. 새로운 알파 릴리스를 필요로 하는 주요 변경 사항이 프리릴리스 과정에서 비교적 늦게 반영된 경우, 릴리스 관리자는 해당 주요 변경 사항 이전의 지점에서 브랜치를 분기할 수도 있습니다. 예를 들어, 다음 예정된 릴리스가 최종 베타 릴리스 또는 첫 번째 릴리스 후보로 계획된 경우 이렇게 하는 것이 합리적일 수 있습니다.
- 알파 릴리스를 선언하는 기준을 What’s New 문서에서 “Porting” 항목을 요구하는 모든 변경 사항을 포함하도록 확장할 수도 있습니다.
- 필요에 따라 알파 릴리스를 선언하는 대신, 릴리스 관리자가 일부 날짜를 미리 알파 릴리스로 선언하고 핵심 개발자에게 그에 맞춰 위험도가 높은 변경 사항의 시기를 조정하도록 요청할 수도 있습니다.
PEP의 구체적인 제안은 검토자가 고려할 수 있는 명확한 예시를 제공하려는 것이지, 프로세스에 대한 실제 경험을 바탕으로 특정 세부 사항을 조정할 수 있는 우리의 능력을 제한하려는 것이 아닙니다.
설계 논의
단순히 X.Y.0 릴리스를 더 자주 진행하는 대신 롤링 프리-프리즈 릴리스를 사용하는 이유는 무엇입니까?
Python 사용자 기반의 상당 부분에서는 새로운 CPython 기능 릴리스의 availability이 해당 릴리스를 채택하는 데 있어 제한 요소가 아닙니다(이 효과는 PyPI 다운로드 메타데이터와 같은 지표에서 확인할 수 있습니다).
따라서 전체 기능 릴리스의 속도를 높이는 모든 제안은 각 릴리스가 이용 가능해지는 즉시 이를 도입하는 사용자의 요구와, 릴리스 수명 주기 중 어느 시점에 거의 모든 릴리스로 마이그레이션할 수 있는 대신 이제 두 번째, 세 번째 또는 네 번째 릴리스마다 도입할 수 있는 사용자의 요구 사이에서 균형을 찾아야 합니다.
이 제안은 CPython 핵심 팀이 새로운 릴리스를 만들어 내는 속도만큼 빠르게 새로운 릴리스를 사용할 수 있는 운영 환경의 관심사에 더욱 구체적으로 맞춘 new 프로덕션 준비 완료 릴리스 스트림을 정의하여 문제에 다른 각도에서 접근하고자 합니다.
“alpha” 및 “beta” 명명 체계를 유지해야 합니까?
제안된 롤링 릴리스에 “a”와 “b” 이니셜을 사용하는 것은 CPython 버전 번호가 공개되는 방식의 실용적인 측면 일부가 부과하는 설계 제약입니다.
구체적으로 알파 릴리스, 베타 릴리스 및 릴리스 후보는 일부 위치에서는 각각 “a”, “b”, “c” 문자열로 보고되는 반면, 다른 위치에서는 16진수 숫자 0xA, 0xB 및 0xC로 보고됩니다. 우리는 이를 유지하는 동시에 모든 Python-Requires 제약 조건이 알파 릴리스가 아니라 베타 릴리스에 대해 표현되도록 하려고 합니다(알파 릴리스가 연속으로 두 번 발생하는 경우 후자는 abi3 안정성 요구 사항을 적용하지 않을 수 있기 때문입니다).
그러나 “a”가 “alpha”를, “b”가 “beta”를 의미한다고 말하도록 강제하는 것은 아무것도 없습니다.
즉, “beta”라는 레이블 때문에 도입을 망설이는 사람들의 채택을 늘리고자 한다면 “alpha” 및 “beta”라는 이름보다 “*A*BI breaking” 및 “*B*inary compatible”이라는 이름을 강조하여 다음과 같이 하는 것이 합리적일 수 있습니다.
- 3.9.0a1: ABI 호환성을 파괴하는 프리-프리즈 릴리스
- 3.9.0b2: 바이너리 호환 프리-프리즈 릴리스
- 3.9.0rc1: 릴리스 후보
- 3.9.0: 최종 릴리스
이 PEP의 이번 개정판은 여기까지 나아가지는 않습니다. 롤링 프리-프리즈 릴리스의 초기 도입을 “beta” 레이블에 익숙한 사람으로 제한하는 것이 좋은 일일 가능성이 높기 때문입니다. 이러한 릴리스의 초기 도입자들이 더 광범위한 Python 생태계 수준에서 발생하는 예상치 못한 결과를 마주하게 될 것이며, 그러한 문제를 해결하는 데 적극적으로 참여할 의지가 필요하기 때문입니다.
그 결과로 얻는 경험이 충분히 긍정적이어서 이 접근 방식을 계속할 가치가 있다고 판단한다면, 향후 “beta” 명칭에서 벗어나는 방안도 고려할 수 있습니다.
안정 릴리스 시리즈와 불안정 릴리스 시리즈를 번갈아 사용하는 대신 롤링 프리-프리즈 릴리스를 사용하는 이유는 무엇입니까?
베타 기간을 롤링 릴리스에 사용하는 대신, 전통적인 안정 릴리스(3.8.x, 3.10.x 등)와 새로운 롤링 릴리스 주기를 사용하는 릴리스 시리즈(3.9.x, 3.11.x 등)를 번갈아 사용하는 방법도 있습니다.
이 아이디어는 PEP 598 및 PEP 602와 동일한 핵심 문제를 안고 있습니다. 현 상태에 만족하는 최종 사용자에게 명확한 보상 혜택을 제공하지 않은 채 변경을 강요하기 때문입니다.
이는 PEP 598에 대해 제기된 주요 우려 중 하나의 영향도 받습니다. 적어도 일부 핵심 개발자와 최종 사용자는 릴리스 버전의 숫자 중 어떤 숫자의 값에도 특정한 의미를 부여하지 않는 것을 강력히 선호합니다. 이러한 커뮤니티 구성원들은 대신 모든 의미상의 중요성이 변경되는 릴리스 번호 내 위치에 부여되기를 선호합니다.
이와 대조적으로 롤링 프리프리즈 릴리스 제안은 제안된 정책 변경이 특정 릴리스가 알파 릴리스인지, 베타 릴리스인지, 릴리스 후보인지, 최종 릴리스인지에 관한 문제를 중심으로 이루어지도록 보장함으로써 이러한 우려를 해결하려고 합니다.
롤링 릴리스 스트림에 Calendar Versioning을 사용하지 않는 이유는 무엇입니까?
Steve Dower가 이 제안에 대해 처음 작성한 글 [1]은 롤링 릴리스 스트림에 달력 버전 관리를 사용할 것을 제안했습니다(따라서 Python 3.8.0 이후의 첫 번째 롤링 프리릴리스는 3.9.0b1이 아니라 Python 2019.12가 되었을 것입니다).
Paul Moore는 이 제안에 두 가지 주요 실무적 문제가 있다고 지적했습니다 [2].
- 달력 기반 버전의 사용자는 기존의 번호가 매겨진 버전과 비교하여 자신이 어디에 해당하는지 명확히 알 수 없게 됩니다.
- 이는 패키징 도구의
Python-Requires메타데이터 처리를 중단시키며, 안정적으로 수정할 명확한 방법도 없습니다(모든 달력 버전이 어떤 표준 버전보다도 최신 버전으로 보이기 때문입니다).
이 PEP는 롤링 릴리스에 기존의 베타 버전 번호를 사용하여 이 두 가지 문제를 모두 해결하려고 합니다.
예를 들어 다음 질문을 생각해 보십시오. “Python 2021.12에는 Python 3.9.0에서 릴리스된 모든 새 기능이 포함되어 있습니까?” 롤링 릴리스에 달력 버전 관리를 사용하면 3.9.0rc1이 롤링 릴리스 시리즈에서 언제 분기되었는지 확인하기 위해 릴리스 일정을 참조하지 않고는 이에 답할 수 없습니다.
이와 대조적으로 롤링 프리프리즈 릴리스에 대한 동일한 질문에는 쉽게 답할 수 있습니다. “Python 3.10.0b2에는 Python 3.9.0에서 릴리스된 모든 새 기능이 포함되어 있습니까?” 질문을 구성하는 것만으로도 답은 분명히 “예, 제거된 잠정적 기능이 아니라면 그렇습니다.”입니다.
베타 번호 지정 방식은 sys.version_info, PY_VERSION_HEX, site-packages 디렉터리 이름 지정, 설치된 Python 바이너리 및 확장 모듈 이름 지정이 어떻게 작동할지와 같은 달력 버전 관리 개념에서 제기되는 다른 질문도 피할 수 있게 합니다.
롤링 프리프리즈 릴리스 사용자는 API 변경을 어떻게 감지합니까?
새 기능을 추가할 때 핵심 개발자는 sys.version_info나 런타임 코드 객체 인트로스펙션 어느 쪽에도 의존하지 않는 메커니즘을 통해 기능 감지와 대체 접근 방식으로의 원활한 대체를 지원하도록 강력히 권장됩니다.
대부분의 경우 영향을 받는 모듈에 대한 간단한 hasattr 검사가 이러한 목적에 충분하지만, 그렇지 않은 경우에는 기능 추가의 일부로 대체 접근 방식을 고려합니다. 이 영역의 선행 사례로는 pickle.HIGHEST_PROTOCOL 속성, hashlib.algorithms_available 집합, 그리고 os 모듈이 플랫폼 종속 기능 감지를 위해 이미 제공하는 다양한 os.supports_* 집합이 있습니다.
롤링 프리프리즈 릴리스에 처음 포함될 때 __future__ 임포트를 통해 명시적으로 활성화해야 하는 기능을 추가하는 것도 가능하며, 해당 기능 플래그가 X.Y.0 릴리스 후보에 처음 등장하기 전에 기본적으로 활성화되었더라도 마찬가지입니다.
이러한 접근 방식의 근거는 이와 같은 명시적 감지 및 활성화를 통해 롤링 프리프리즈 릴리스 스트림 사용자가 잠정적 기능이 제거되거나 변경되는 시점을 쉽게 알아차리거나(예를 들어 기능 플래그가 더 이상 존재하지 않으면 컴파일 시 from __future__ 임포트가 오류를 일으킵니다), 이전 기능으로 안전하게 대체할 수 있게 된다는 점입니다.
인터프리터의 풍부한 속성 조회 메커니즘을 사용하면 sys.version_info의 값에 대한 검사에는 실용적으로 추가할 방법이 없는 잠정적 또는 사용 중단 예정 임포트와 속성에 대해서도 경고를 추가하도록 선택할 수 있습니다.
X.Y.0rc1 이후 재빌드를 강제하기 위해 새로운 프리프리즈 ABI 플래그를 추가하는 이유는 무엇입니까?
핵심 개발 팀은 현재 ABI 동결 날짜 이전에 X.Y 시리즈의 공개 사전 빌드 바이너리를 만드는 것을 적극적으로 권장하지 않습니다.
그렇게 하는 이유는 안정 버전인 X.Y.0 릴리스에서 발생한 고통스러운 디버깅 세션의 원인이 “우리 의존성인 ‘superfast-binary-operation’이 X.Y.0a3의 CPython ABI 변경의 영향을 받았는데, 그 이후 프로젝트에서 새 빌드를 공개하지 않았습니다”로 밝혀지는 위험을 피하기 위해서입니다.
제안된 프리프리즈 ABI 플래그를 적용하면 릴리스 도입 과정의 이 측면은 현재 상태에서 본질적으로 변경 없이 계속됩니다. 새로운 CPython X.Y 릴리스 시리즈가 ABI 동결에 도달함 -> 패키지 관리자가 해당 릴리스 시리즈의 새 바이너리 확장 모듈을 공개함 -> 최종 사용자는 호환되지 않는 ABI에 맞춰 빌드했기 때문이 아니라 실제 버그로 인한 세그먼테이션 오류만 겪게 됩니다.
따라서 새로운 프리프리즈 ABI 플래그의 주요 목표는 롤링 프리프리즈 릴리스 자체의 사용자 경험을 개선하는 것입니다. 이를 통해 ABI 동결 이전에 바이너리 아티팩트 공개를 적극적으로 권장하지 않게 만드는 현재의 문제를 걱정하지 않고 해당 릴리스용 사전 빌드 바이너리 아카이브를 공개할 수 있습니다.
이상적인 경우 패키지 관리자는 X.Y.0a1에서 프리프리즈 바이너리 빌드 하나만 공개한 다음, X.Y.0rc1 이후에 동결 후 빌드를 공개하면 됩니다. 그 사이에 재빌드를 필요로 하는 유일한 상황은 프로젝트가 중간의 알파 릴리스에서 발생한 CPython ABI 변경의 실제 영향을 받은 경우입니다.
구체적인 예로 ABI 변경이 포함된 릴리스가 X.Y.0a1, X.Y.0a5, X.Y.0a7의 세 개였다고 가정하는 상황을 생각해 보십시오. 그러면 X.Y.0a7 ABI가 이후의 모든 베타 릴리스와 X.Y.0rc1까지 이어지는 ABI가 됩니다. (그림 1에 설명된 상황입니다.)
롤링 릴리스 스트림에서 알파 릴리스가 나올 때마다 모든 사람에게 전체를 재빌드하도록 강제하면 게시자가 롤링 릴리스를 지원하는 것이 수고에 비해 가치가 없다고 판단할 가능성이 거의 확실히 높아집니다. 따라서 X.Y.0a1에 대해 빌드된 모듈을 X.Y.0a7에 대해 로드할 수 있도록 하려고 합니다. 두 버전은 아마도 호환될 것이기 때문입니다(CPython이 공개하는 모든 C API를 사용하는 프로젝트는 극소수이며, 대부분의 ABI 변경은 하나의 특정 API에 영향을 줍니다).
그러나 X.Y.0rc1을 게시하면 X.Y.0a1 및 X.Y.0a4에 맞춰 빌드된 모든 바이너리가 최종 사용자 경험에서 완전히 제거되도록 하려고 합니다. X.Y.0a7 및 그 이후의 베타 릴리스에 맞춰 빌드된 결과물은 계속 유지할 수 있다면 좋겠지만(당시에는 알지 못했더라도 실제로는 동결 후 ABI에 맞춰 빌드된 것으로 밝혀졌기 때문입니다), 이를 잃더라도 현 상태보다 더 나쁜 것은 아닙니다.
이는 사전 동결 플래그가 이 문제를 해결하기 위해 “가능한 한 가장 단순하게 작동하는 것”이라는 의미입니다. 즉, 새로운 ABI 플래그일 뿐이며, 이미 ABI 플래그를 처리할 수 있는 도구를 보유하고 있습니다(인터프리터와 패키지 게시 및 설치 도구 모두에서 사용할 수 있습니다).
사전 릴리스에 비해 ABI 플래그가 변경되었으므로 프로젝트는 새 릴리스를 게시할 필요조차 없습니다. 오늘날에도 가능한 것처럼 기존 릴리스에 새 휠 아카이브를 업로드할 수 있습니다.
마지막 알파 또는 그 이후의 베타 릴리스에 맞춰 빌드된 모든 것을 소급하여 허용할 수 있는 더 영리한 방식도 아마 가능하겠지만, 이 PEP를 채택하는 데 필요한 것으로 간주되지는 않습니다. 처음에는 단순한 사전 릴리스 ABI 플래그로 시작하더라도 향후에 더 정교한 접근 방식을 고안할 수 있기 때문입니다.
X.Y.0a1 이후에 추가 알파 릴리스를 허용하는 이유는 무엇입니까?
이상적인 세계라면 전체 CPython ABI에 대한 모든 호환성이 깨지는 변경 사항이 파일 시스템 레이아웃 변경과 함께 X.Y.0a1에 반영되고, 그 이후에는 해당 릴리스 시리즈의 ABI가 안정적으로 유지될 것입니다.
그러나 최근의 역사는 실제로 그러한 약속을 하고 이를 지킬 수 있으리라는 점을 시사하지 않으므로, 이 PEP는 사전 동결 기간 전체에 걸쳐 ABI 변경이 점진적으로 이루어지고 X.Y.0rc1을 준비할 때 X.Y.z 유지 관리 브랜치를 생성하면서만 완전한 동결이 이루어진다고 가정합니다.
CPython 핵심 개발에 미치는 영향
CPython 핵심 개발에서 가장 큰 변화는 master 브랜치를 더욱 일관되게 릴리스 준비 상태로 유지해야 한다는 점입니다.
이를 위한 주요 요구 사항은 안정적인 BuildBot 팜을 녹색 상태로 유지하는 것이겠지만, 순차적으로 진행되는 사전 동결 릴리스를 사용하는 사용자에게 도움이 되도록 문서의 개발 버전도 최신 상태로 유지하도록 장려할 것입니다. 여기에는 변경 사항이 구현될 때마다 초안 형태의 What’s New 항목을 제공하는 것도 포함됩니다. 초기 버전은 비교적 간략할 수 있지만, 베타 릴리스 사용자들의 피드백을 바탕으로 이후 확장할 것입니다.
CPython C API를 작업하는 핵심 개발자에게는 NEWS 파일 조각에서 ABI 호환성이 깨지는 변경 사항을 일관되게 표시해야 한다는 새로운 요구 사항도 생깁니다.
안정 ABI라는 구체적인 주제와 관련해서는 대부분의 API 설계가 먼저 전체 CPython API의 잠정적인 일부로 도입되고(사전 동결 릴리스 사이에서 변경할 수 있도록 하면서), 개발자들이 해당 인터페이스가 실제로 안정적이라고 확신하게 된 후에야 안정 ABI로 승격되는 과정을 거칠 수 있습니다.
API가 안정 ABI 외부에서는 유용한 목적을 전혀 제공하지 않는 드문 경우에만, 잠정적인 안정 ABI 추가 사항을 포함하는 알파 릴리스를 게시하는 것이 잠정적인 CPython API에서 설계를 계속 반복하는 것보다 의미가 있을 수 있습니다.
Python 라이브러리 개발에 미치는 영향
이 PEP가 목표를 달성한다면, 순차적으로 진행되는 사전 동결 릴리스 스트림을 지원하는 일은 라이브러리 작성자에게 안정 릴리스를 지원하는 것보다 크게 더 고통스럽지 않을 것입니다.
순수 Python 패키지 게시자의 경우, 이는 “py3” 태그가 지정된 휠 아카이브를 게시하고, 가능하다면 순차적으로 진행되는 사전 동결 릴리스 스트림을 테스트 매트릭스에 추가하는 일이 될 것입니다.
바이너리 확장 모듈 게시자의 경우 선호되는 선택지는 가능하다면 안정 C ABI를 대상으로 하는 것입니다. 그러면 단일 사전 빌드 휠 아카이브로 순차적으로 진행되는 사전 동결 릴리스 스트림을 포함한 여러 Python 버전을 지원할 수 있어 순수 Python 패키지와 유사한 경험을 누릴 수 있습니다.
이 선택지가 모든 라이브러리에 실행 가능한 것은 아니며, 해당 작성자들이 바라는 결과는 최초 X.Y.0a1 릴리스에 맞춰 빌드한 추가 휠 아카이브 하나를 빌드하고 게시하여 순차 릴리스를 지원할 수 있게 되는 것입니다. 이후 X.Y.0rc1 이상에 맞춰 수행하는 빌드는 최종 안정 릴리스만 지원하는 경우에 필요했을 빌드와 동일합니다.
따라서 이 두 빌드 외에 추가로 휠을 빌드해야 하는 경우는 해당 라이브러리가 두 시점 사이에 발생한 다른 알파 릴리스의 ABI 호환성 변경에 직접 영향을 받는 경우뿐입니다.
순차적으로 진행되는 사전 동결 릴리스 스트림을 이용할 수 있으면 더 많은 CI 제공자가 “CPython 베타 릴리스” 테스트 옵션을 제공하기도 쉬워질 수 있습니다. 현재 이 기능은 CPython master 브랜치에서 자체 빌드를 생성하고, 테스트하고, 게시하는 데 필요한 시간과 노력을 기꺼이 들일 수 있는 CI 제공자만 이용할 수 있습니다(예: [6]).
제안된 Scientific Python 생태계 지원 기간에 미치는 영향
SciPy 2019에서의 논의를 바탕으로, NEP(NumPy Enhancement Proposal) 29가 Scientific Python 생태계 전반에서 이전 Python 버전에 대한 지원을 중단하는 공통 규칙을 제안하기 위해 초안 작성되었습니다 [3].
해당 정책의 정확한 문구는 아직 논의 중이지만, 2019년 10월 20일 기준 초안 제안은 프로젝트가 지난 42개월 이내에 게시된 모든 Python 기능 릴리스를 지원하고, 최소한 최신 Python 기능 릴리스 2개를 지원할 것을 권장합니다.
18개월의 기능 릴리스 주기에서는 최소한 최신 기능 릴리스 2개를 항상 지원한 다음, X.(Y+2).0이 릴리스된 후 약 6개월이 지나면 모든 X.Y.Z 릴리스에 대한 지원을 중단하게 됩니다. 이는 대략 2년에 한 번씩 최신 기능 릴리스 3개를 지원하는 6개월의 기간이 있음을 의미합니다.
12개월의 릴리스 주기에서는 최소한 최신 기능 릴리스 3개를 항상 지원한 다음, X.(Y+3).0이 릴리스된 후 약 6개월이 지나면 모든 X.Y.Z 릴리스에 대한 지원을 중단하게 됩니다. 이는 매년 절반의 기간에는 최신 기능 릴리스 4개가 지원되고, 나머지 절반의 기간은 그해의 기능 릴리스를 준비하는 데 사용되기를 기대한다는 의미입니다.
24개월 릴리스 주기의 경우 두 번째 절이 첫 번째 절보다 우선하며, 가장 최근의 CPython 기능 릴리스 두 개를 일관되게 지원하기 위해 권장 Python 버전 지원 기간이 최초 X.Y.0 릴리스로부터 48개월로 늘어납니다. 롤링 릴리스 스트림도 지원하는 프로젝트의 경우, 지원되는 기능 릴리스의 수가 세 개로 늘어날 것입니다.
핵심 개발 스프린트를 위한 릴리스 주기 정렬
이 PEP의 제안에 따르면, 핵심 개발 스프린트의 초점이 2년 주기 내 현재 위치에 따라 약간씩 이동할 것으로 예상됩니다.
릴리스 연도에는 PyCon US의 시기가 첫 번째 릴리스 후보가 나오기 전에 새 기여자들이 버그 수정과 소규모 기능 작업을 하기에 적합하며, 한편 Language Summit과 핵심 개발자 논의는 다음 릴리스 시리즈의 계획에 초점을 맞출 수 있습니다.
릴리스 연도의 알파 이전(pre-alpha) 핵심 개발 스프린트는 이전 릴리스에 대해 받은 피드백을 반영할 기회를 제공하며, 이는 다음 유지보수 릴리스의 일부로(버그 수정 및 프로비저널 API에 대한 피드백의 경우) 또는 다음 릴리스 시리즈의 첫 번째 알파 릴리스의 일부로(안정 API에 대해 받은 피드백의 경우) 이루어집니다.
이러한 초기 알파 릴리스는 또한 전체 CPython ABI에 대한 ABI 파괴적 변경 사항이 우선적으로 반영되는 대상이 될 것입니다 (릴리스 주기 후반의 변경 사항도 이 PEP에서 설명한 대로 여전히 허용되지만, X.Y.0a1 릴리스에 반영하면 사전 빌드된 바이너리 패키지 배포자들에게 추가 작업을 유발하지 않게 됩니다).
다음 릴리스 주기를 위한 운영위원회(Steering Council) 선거도 알파 이전 개발 스프린트와 비슷한 시기에 열릴 가능성이 있습니다.
릴리스가 없는 해에는 두 행사 모두 다가오는 유지보수 릴리스와 프리즈 이전(pre-freeze) 릴리스에만 초점을 맞출 것입니다. 이러한 덜 바쁜 해에는 릴리스 후보 준비 과정에 영향을 주지 않으면서 다양한 프로세스 변경과 인프라 업그레이드를 다룰 기회가 생기기를 기대할 수 있습니다.
주요 Linux 배포판을 위한 릴리스 주기 정렬
일부 롤링 릴리스 Linux 배포판(예: Arch, Gentoo)은 이 PEP에서 제안하는 새로운 롤링 프리즈 이전 릴리스를 채택할 수 있는 위치에 있을 수 있지만, 대부분의 배포판은 기존에 확립된 릴리스를 계속 사용할 것으로 예상됩니다.
이 PEP에서 제안하는 최종 릴리스의 구체적인 날짜는 Ubuntu와 Fedora Linux 배포판의 연례 10월 릴리스에 대한 기능 프리즈 일정과 맞추기 위해 선정된 것입니다.
Fedora와 Ubuntu 모두에게, 이는 릴리스 후보 단계가 배포판 릴리스의 개발 기간과 정렬됨을 의미하며, 이는 그들이 새 버전을 테스트하고 잠재적인 회귀 및 호환성 문제에 대한 피드백을 제공하기에 이상적인 시기입니다.
Ubuntu의 경우, 이는 또한 4월 LTS 릴리스가 새 시스템 Python 버전을 사용하는 완전한 단기 릴리스 주기의 혜택을 받게 되면서도, 다음 Ubuntu LTS 릴리스까지 대부분의 기간 동안 해당 CPython 릴리스가 업스트림 버그 수정에 계속 열려 있음을 의미합니다.
이 PEP의 구체적인 제안과 일관되게 잘 맞지 않을 가능성이 있는 유일한 Linux 릴리스 주기 정렬은 Debian과의 정렬로, Debian은 2005년 이후 홀수 연도의 상반기에 릴리스되어 왔습니다 (Ubuntu LTS 릴리스와 약 12개월 차이).
연례 릴리스 제안인 PEP 602에 따르면 Debian과 Ubuntu LTS는 모두 약 6개월 된 시스템 Python 버전을 일관되게 제공받지만, 서로 다른 Python 버전을 일관되게 선택하게 됩니다.
2년 주기이고 CPython 릴리스가 연도 후반부에 있을 경우, 이들은 서로 같은 버전을 선택할 가능성이 높지만, 그중 하나는 Linux 배포판이 출시될 시점에 최신 베타 릴리스보다 18개월 이상 뒤처진 CPython 릴리스를 선택하게 될 것입니다.
그러한 상황이 실제로 발생하고, 이것이 바람직하지 않다고 여겨지는 경우 (그러나 Debian이 자신들의 릴리스 시기를 조정할 만큼 충분히 바람직하지 않은 것은 아닌 경우), 바로 그 지점에서 PEP 598의 “점진적 기능 릴리스(incremental feature release)” 제안이 갖는 추가적인 복잡성이 가치를 발휘할 수 있습니다.
(CPython 릴리스를 Debian 및 Ubuntu LTS 릴리스와 같은 연도 반기로 옮기면 이 문제를 완화하는 데 도움이 될 수 있지만, 동시에 새로운 문제도 발생시킵니다. CPython 릴리스 일정의 지연이 Linux 배포판의 릴리스 일정에 직접 영향을 미치거나, 그렇지 않으면 배포판이 18개월보다 더 오래된 Python 버전을 출시하게 되는 결과를 낳을 수 있습니다)
단순한 배포 환경에 대한 영향
이 PEP의 목적상, “단순한” 배포 환경이란 모든 대상 환경을 동시에(또는 적어도 새로운 상위 수준 애플리케이션 버전의 출시에 앞서) 새 Python 릴리스로 업데이트하는 것이 간단하며, 발생하는 모든 릴리스 전 테스트가 단일 Python 마이크로 버전만을 대상으로 하면 되는 모든 사용 사례를 말합니다.
가장 단순한 이러한 사례는 개인 용도의 스크립팅으로, 테스트 환경과 대상 환경이 완전히 동일한 환경입니다.
마찬가지로 단순한 환경으로는 컨테이너화된 웹 서비스가 있는데, 이는 CI 파이프라인에서 사용되는 것과 동일한 Python 컨테이너가 배포 시에도 사용되는 경우이며, 대상 시스템에 미리 존재하는 Python 배포에 의존하는 대신 자체 Python 런타임을 번들로 포함하는 모든 애플리케이션도 마찬가지입니다.
이러한 사용 사례에서는 이 PEP의 영향을 최소화하는 간단한 방법이 있습니다. 즉, 안정 릴리스를 계속 사용하고 롤링 프리즈 이전 릴리스는 무시하는 것입니다.
이러한 환경에서 실제로 롤링 프리즈 이전 릴리스를 채택하려면, 주된 과제는 다음 프리즈 이전 릴리스가 베타 릴리스가 아니라 알파 릴리스인 경우 확장 모듈의 세그폴트(segfault) 가능성을 다루는 것이 될 것이며, 이는 CPython ABI가 호환되지 않는 방식으로 변경되었을 수 있음을 나타냅니다.
사용 중인 모든 확장 모듈이 안정 ABI를 대상으로 한다면 문제가 없으며, 모든 것이 안정 릴리스에서와 마찬가지로 원활하게 작동할 것입니다.
대안으로, “모든 확장 모듈을 다시 빌드하고 다시 캐시”하는 것이 알파 릴리스로 업데이트하는 과정의 일부로 표준 활동이 될 수 있습니다.
마지막으로, 실제로 무언가가 깨질 때까지는 그냥 신경 쓰지 않다가, 새로운 알파 또는 베타 릴리스에서 발견되는 다른 라이브러리 호환성 문제와 마찬가지로 처리하는 것도 합리적일 수 있습니다.
확장 모듈 ABI 호환성 외에, 롤링 프리즈 이전 릴리스를 사용할 때 추가적인 복잡성의 또 다른 주요 지점은 pickle 및 SQLite와 같이 독립적으로 버전이 관리되는 기능에 대한 “롤백” 호환성이 될 것이며, 이는 베타 스트림에서 새롭거나 프로비저널한 기능을 사용하면 안정 릴리스에서 읽을 수 없는 파일이 생성될 수 있기 때문입니다. 이러한 종류의 기능을 사용하면서 동시에 이전 안정 CPython 릴리스로 신뢰성 있게 롤백할 수 있는 능력이 필요한 애플리케이션은, 오늘날과 마찬가지로, 릴리스 전 버전을 채택하지 않는 것이 권장됩니다.
복잡한 배포 환경에 대한 영향
이 PEP의 목적상, “복잡한” 배포 환경이란 위의 “단순 배포” 기준을 충족하지 않는 사용 사례를 말합니다. 여기에는 서로 다른 여러 버전의 파이썬을 사용하는 경우, 개인화된 빌드의 파이썬을 사용하는 경우, 또는 배포 전에 새 버전의 사용을 승인해야 하는 “게이트키퍼”가 존재하는 경우가 포함될 수 있습니다.
예를 들어, 표준 운영 환경의 일부로 사용자의 컴퓨터에 파이썬을 설치하는 조직과 표준 빌드 환경을 제공하는 조직이 이 범주에 속합니다. 일관되게 빌드되고 검증된 패키지 모음을 제공하는 conda-forge나 WinPython 같은 배포판도 비슷한 방식으로 영향을 받습니다.
이러한 조직들은 대개 높은 안정성을 선호하거나(예를 들어 Debian, RHEL/CentOS, Ubuntu LTS 같은 안정적인 리눅스 배포판의 시스템 파이썬을 기꺼이 선호하는 파이썬 환경으로 사용하는 모든 이들), 빠른 회전 주기를 선호합니다(예를 들어 최신 CPython 사전 릴리스에 정기적으로 기여하는 이들).
경우에 따라서는 다음과 같이 서로 다른 목적으로 동일 조직 내에 두 사용 모델이 함께 존재할 수도 있습니다:
- 미션 크리티컬 시스템에는 안정적인 파이썬 환경을 사용하되, 데이터 과학자들에게는 임시 데이터 분석을 위해 최신 사용 가능 버전을 사용하도록 허용하는 경우
- 하드웨어 제조사가 프로덕션 펌웨어의 일부로는 안정적인 파이썬 버전을 배포하되, 자동화된 통합 테스트의 개발 및 실행에는 최신 사용 가능 버전을 사용하는 경우
어떤 릴리스 모델을 사용하든, 파이썬의 새 릴리스가 나올 때마다 이러한 조직들에게는 작업이 발생합니다. 이 작업에는 파이썬 자체에 대한 법률적, 보안적, 기술적 검토, 영향력 있는 변경 사항에 대한 평가 및 검증, 패치 재적용, 서드파티 의존성의 재컴파일 및 테스트, 그리고 그 이후에야 비로소 이루어지는 배포가 포함될 수 있습니다.
업데이트를 신속히 적용할 수 있는 조직들은 더 잦은 베타 릴리스를 활용할 수 있어야 합니다. 각 업데이트마다 오늘날 요구되는 것과 비슷한 조사 작업이 여전히 필요하겠지만, 각 릴리스가 현재 모델에서보다 이전 릴리스와 더 유사해질 것이므로 릴리스당 필요한 작업량은 줄어들어야 합니다. 제안된 2개월마다 릴리스하는 모델의 장점 중 하나는, 조직이 모든 베타 릴리스를 채택하는 것부터 분기마다 하나, 6개월마다 하나, 또는 1년마다 하나를 채택하는 것까지 자신만의 도입 주기를 선택할 수 있다는 점입니다. 그 이상으로는 대신 안정 릴리스를 계속 사용하는 편이 더 합리적일 것입니다.
더 엄격한 평가를 거치거나 안정성을 선호하는 조직의 경우, 안정 릴리스의 더 긴 릴리스 주기는 업데이트에 필요한 연간 노력을 줄여 주고, 더 긴 릴리스 후보 기간은 X.Y.0 릴리스 이전에 내부 테스트를 할 시간을 더 많이 제공하며, 베타 기간 동안 다른 이들의 더 많은 사용은 초기 릴리스에 대한 확신을 더 크게 제공할 것입니다. 한편, 해당 조직은 호환성을 깨뜨리는 변경에 대한 걱정 없이 더 오랜 기간 유지 보수 릴리스를 통해 자신 있게 업그레이드할 수 있습니다.
감사의 말
관련 PEP 602를 작성하고 CPython 릴리스 주기의 개선 가능성에 관한 논의를 촉발한 Łukasz Langa와 이 PEP의 초안에 건설적인 피드백을 제공한 Kyle Stanley 및 h-vetinari에게 감사드립니다.
참고 자료
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.