[Rejected] PEP 497 - A standard mechanism for backward compatibility
원문 링크: PEP 497 - A standard mechanism for backward compatibility
상태: Rejected 유형: Process 작성일: 04-Aug-2015
PEP 497 – 하위 호환성을 위한 표준 메커니즘
작성자: Ed Schofield
거부 공지
스티어링 위원회(steering council)는 이 제안의 __past__
측면이 잠재적 이점에 비해 너무 복잡하다고 판단하여 거부했습니다. 하위 호환성에 대한 더 강력한 요구사항은 PEP 387에서 다루어야 합니다.
개요
이 PEP는 PEP 5, PEP 236, PEP 387을 보완하며 유사한 목표를 공유합니다.
이 PEP는 “언어 발전 가이드라인”인 PEP 5를 지원하기 위한 추가적인 호환성 메커니즘의 필요성을 설명합니다. “미래로 돌아가기”인 PEP 236은 PEP 5를 지원하기 위한 전방 호환성(forward compatibility) 메커니즘을 도입했지만, 새로운 하위 호환성(backward compatibility) 메커니즘은 해당 PEP의 범위를 벗어난다고 언급했습니다. 관련 PEP(진행 중)는 이러한 하위 호환성 메커니즘을 도입합니다.
PEP 5는 “이 PEP [PEP 5]는 하위 호환 가능한 파서의 동적 로딩과 같은 다른 호환성 전략을 대체하거나 배제하지 않는다”고 언급합니다.
배경
PEP 236에 따르면: “때때로 Python은 핵심 언어 구성 요소의 공표된 의미를 호환되지 않게 변경하거나, 우발적인(구현 종속적인) 동작을 어떤 식으로든 변경합니다. 이는 결코 변덕스럽게 이루어지지 않으며, 항상 장기적으로 언어를 개선하기 위한 목표로 이루어지지만, 단기적으로는 논쟁의 여지가 많고 혼란스럽습니다. PEP 5, 언어 발전 가이드라인은 이러한 어려움을 완화할 방법을 제안하며, 이 PEP [PEP 236]는 이를 지원하기 위한 일부 장치를 도입합니다.”
또한 PEP 236은 다음과 같이 언급합니다: “future_statement
의 목적은 최신 릴리스를 제때 사용하는 사람들의 삶을 더 쉽게 만드는 것입니다. 그렇지 않다고 해서 당신을 싫어하는 것은 아니지만, 당신의 문제는 훨씬 해결하기 어렵고, 그러한 문제를 가진 누군가가 그것들을 다루는 PEP를 작성해야 할 것입니다. future_statement
는 다른 대상을 목표로 합니다.”
현재 상황
핵심 언어 구문이나 의미에 호환되지 않는 변경이 있을 때, Python은 현재 새로운 구문이나 의미를 강제하는 릴리스가 나올 때까지 전방 호환성을 제공하기 위해 future_statement
메커니즘을 제공하지만, 이 릴리스 이후에 하위 호환성을 제공하기 위한 상응하는 표준 메커니즘은 제공하지 않습니다.
문제
이러한 비대칭성으로 인해, 파괴적인 변경(breaking change)과 관련하여 이전(변경 전) 버전의 Python 인터프리터가 새로운(변경 후) 버전보다 더 유능합니다. 이전 인터프리터는 변경 이전에 설계된 코드와 새로운 코드 모두를 사용할 수 있는 반면, 새로운 인터프리터는 변경된 기능을 지원하도록 업그레이드된 코드만 사용할 수 있습니다.
예를 들어, PEP 236이 future_statement
메커니즘을 도입한 직후인 2001년에 PEP 238에서 도입된 나눗셈(division) 연산자 변경을 고려해 보세요. PEP 238은 Python 2.x 시리즈에서 “참 나눗셈(true division)”을 위한 유용한 전방 호환성 메커니즘들을 설명하지만, Python 3.0에서 “참 나눗셈”이 처음으로 강제된 이후를 위한 하위 호환성 메커니즘은 포함하지 않습니다. Python 3.0 이후 버전은 이전 “고전 나눗셈(classic division)” 의미를 기대하는 코드를 위한 from __past__ import division
과 같은 하위 호환성 메커니즘을 제공하지 않는 반면, Python 3.0 이전 버전은 “고전 나눗셈” 코드와 “참 나눗셈”을 기대하는 코드와의 전방 호환성을 모두 지원합니다. 이로 인한 또 다른 결과는 다양한 나눗셈 관련 Python 코드에 대해 “가장 호환성 있는” 인터프리터는 파괴적인 변경이 처음으로 강제되기 전 버전인 Python 2.7이라는 것입니다.
“하향 업그레이드(downhill upgrades)”를 가능하게 하는 하위 호환성
이러한 상황과 대조적으로, 오피스 스위트와 같은 응용 소프트웨어의 새로운 버전은 다양한 버전의 데이터 파일 형식을 로드하는 기능에 있어 이전 버전보다 더 유능한 경향이 있습니다. 일반적으로 새로운 응용 프로그램 버전은 최신 또는 이전 데이터 형식의 데이터를 투명하게 로드할 수 있으며, 새로운 버전은 기본적으로 최신 형식으로 데이터를 저장합니다. 새로운 응용 소프트웨어 버전은 기본적으로 하위 호환됩니다. 전방 호환성은 비교적 드뭅니다.
이 정책은 새로운 응용 소프트웨어 사용자에게 이전 소프트웨어 사용자보다 이점을 제공하며, 이전 소프트웨어는 일반적으로 새로운 형식의 데이터를 로드할 수 없습니다. 때로는 새로운 소프트웨어 응용 프로그램 버전을 사용하는 사용자가 이 옵션을 명시적으로 선택하여 이전 버전으로 데이터를 내보내는 것이 가능합니다. 이러한 경우, 이것이 가능하게 하는 전방 호환성은 완벽할 수도 있고 그렇지 않을 수도 있습니다. 일부 기능이 누락되거나 결과가 최적이 아닐 수 있습니다. 따라서 업그레이드는 쉽지만, 다운그레이드는 더 어렵습니다.
새로운 매력적인 기능과 하위 호환성 기능을 포함하는 이러한 정책에서 많은 사용자에 걸쳐 나타나는 행동은 각 개별 사용자가 자신의 응용 프로그램 버전을 업그레이드해야 한다는 자연스러운 압력이 생기고, 다른 사용자와 데이터 파일을 더 많이 교환할수록 이 압력은 더욱 심해진다는 것입니다.
제안 - 1부
이 PEP는 두 가지 구체적이고 관련된 제안을 합니다. 첫 번째는 다음과 같습니다.
PEP 5의 “하위 호환되지 않는 기능 도입을 위한 단계” 섹션에 6단계가 추가되어, 핵심 언어 구문이나 의미에 호환되지 않는 변경이 있을 때, Python 개발 커뮤니티(Python-dev)의 정책은 가능한 한 전방 호환성을 위한 새로운 future_statements
와 같은 메커니즘 외에, 파괴적인 변경이 기본값으로 채택된 이후의 미래 Python 버전을 위한 하위 호환성 메커니즘을 고려하고 제공하는 것을 선호하고 기대한다는 것을 명시해야 합니다. 또한, PEP 387, “하위 호환성 정책”(수락된다면)도 동일한 6단계를 추가해야 합니다.
예시
이 PEP가 어떻게 적용되는지에 대한 예시로, “참 나눗셈” PEP (238)의 최신 개정판이 오늘 제안되었다면 불완전한 것으로 간주될 것입니다. PEP 238은 제안으로 인해 발생하는 “심각한 하위 호환성 문제”를 언급하고 추상(Abstract) 및 API 변경(API Changes) 섹션에서 전방 호환성을 위한 여러 조치를 설명합니다. 또한 c.l.py
에서 제기된 일부 하위 호환성 아이디어, 예를 들어 “모듈에서 고전 나눗셈 의미를 사용하려면 from __past__ import division
사용”을 언급하지만, 제안의 일부로 하위 호환성 계획을 제시하지는 않습니다.
이 PEP가 수락된다면, PEP 238과 같이 대규모 호환성 함의를 가진 제안은 파괴적인 변경이 발효된 이후의 미래 Python 버전 사용자가 코드에서 고전 나눗셈 동작을 쉽게 다시 활성화할 수 있도록 하는 하위 호환성 계획도 동반해야 할 것으로 예상됩니다.
제안 - 2부
두 번째 제안은 다음과 같습니다.
Python은 전방 호환성을 위한 __future__
모듈 메커니즘과 병렬로 표준 하위 호환성 메커니즘을 제공해야 합니다.
이 문서에서는 이를 “ __past__
“ 메커니즘이라고 부르지만, __future__
모듈 및 future_statement
메커니즘의 모든 특성을 가질 필요는 없습니다.
__past__
메커니즘의 특정 형식과 구현은 별도의 PEP(진행 중)의 주제입니다. 그러나 이 PEP는 __past__
메커니즘이 __future__
를 위한 PEP 296에 설명된 것과 유사한 기준을 충족하도록 설계되어야 한다고 권장합니다. 구체적으로:
a. 개별 모듈이 모듈별로 이전 Python 버전에서 다시 활성화할 구식 동작을 지정할 수 있도록 해야 합니다.
b. Python 3.6+ 및 이전 버전의 포인트 릴리스 모두 __past__
메커니즘을 호출하는 사용자 모듈에 대해 이전 Python 구문 또는 의미와의 하위 호환성을 다시 도입할 수 있을 만큼 충분히 유연해야 합니다.
c. 특정 __past__
기능 또는 하위 호환성을 위한 __past__
메커니즘의 존재 자체를 모르는 2.x와 같은 이전 Python 버전에서 __past__
동작을 호출하도록 보강된 이전 코드를 실행할 수 있어야 합니다.
반대 예시
이러한 기준을 위반할 __past__
메커니즘의 일부 구현은 다음과 같습니다.
a. 임포트 훅(Import hooks). 이들은 일반적으로 모듈별로 작동하지 않으며, 대신 모듈 내에서 임포트된 모든 새 모듈에 재귀적으로 적용됩니다.
b. 이전 버전과 호환되지 않는 Python 3.6의 새로운 구문 조각 또는 새로운 의미.
c. 이전 Python 버전에 같은 이름으로 존재하는 Python 표준 라이브러리의 모듈에 Python 3.6에서 추가된 함수.
이점
이 제안을 채택함으로써 Python 개발 커뮤니티(Python-dev)가 얻는 이점은 미래의 하위 호환되지 않는 변경이, 각 변경에 해당하는 __past__
기능이 구현되어 미래 Python 버전 사용자가 쉽게 호출할 수 있다면, 덜 혼란스러울 수 있다는 것입니다. 이는 언어가 설계상의 실수를 수정하기 위해 더 빠르고 효과적으로 진화하는 데 도움이 될 수 있습니다.
보수적인 사용자에게는 이점이 명확합니다. 그들은 각 모듈에 __past__
구문(아마도 한 줄)을 추가하는 것만으로 최신 호환성 파괴 Python 버전에 대한 지원을 코드에 추가할 수 있으며, 이는 자동화될 수 있습니다. 그런 다음 인터프리터를 최신 버전으로 업그레이드하고 최신 Python 기능에 접근할 수 있습니다.
커뮤니티에 대한 이점은, 만약 만 명의 사용자가 패키지 XYZ에 의존하고, 패키지 XYZ가 최신 Python 버전에 대한 지원을 쉽게 추가할 수 있다면, 그 만 명의 사용자도 패키지 XYZ가 이를 수행하기를 기다리지 않고 빠르게 최신 Python 버전으로 업그레이드할 수 있다는 것입니다.
질문 및 답변
Q1: 이 PEP는 Python이 각 하위 호환되지 않는 기능에 대해 두 가지 가능한 의미 집합을 영원히 유지하도록 요구합니까?
A1: 절대 아닙니다. 레거시 기능은 적절할 때(즉, 사용자 기반의 대다수가 새로운 Python 버전으로 마이그레이션했을 때) 여전히 단계적으로 폐지될 수 있습니다. 이 PEP는 단순히 호환성을 위한 개발 노력의 초점을 100% 전방에서 최소 50% 하위로 전환할 것을 제안합니다. 하위 호환성은 사용자 기반이 최신 Python 인터프리터 버전을 채택하도록 허용하는 두 개념 중 더 강력한 것입니다.
대부분의 사용자가 Python 2.1을 넘어선 지 오래되었기 때문에, 비-중첩 스코프(non-nested scopes)에 대한 하위 호환성에 대해 대부분의 사용자가 오랫동안 신경 쓰지 않았다는 점에 주목하십시오.
Q2: 하지만 Python 개발 커뮤니티(Python-dev)는 이미 과부하 상태이며 추가적인 복잡성을 구현/유지할 여력이 없습니다!
A2: Python 개발 커뮤니티(Python-dev)는 개발자 커뮤니티에 자신들이 중요하게 생각하는 레거시 언어 기능에 대한 Python의 하위 호환성을 유지하도록 요청할 수 있습니다. 커뮤니티가 특정 구식 동작에 대해 더 이상 신경 쓰지 않게 되면, Python 개발 커뮤니티(Python-dev)도 더 이상 신경 쓰지 않아도 됩니다.
__past__
메커니즘은 핵심 개발자의 부담을 줄이기 위해, 예를 들어 표준이지만 “승인된” PyPI 패키지로서 커뮤니티에 의해 확장 가능하도록 설계될 수 있습니다.
Q3: 하위 호환성 기능이 Python에 많은 불필요한 코드(cruft)와 비대화(bloat) 및 부담(baggage)을 초래하지 않을까요?
A3: 반드시 그렇지는 않습니다. 첫째, Python의 새로운 호환성 파괴 기능에 대한 제안은 관련 __past__
기능 구현의 단순성과 유지 보수성을 미리 평가하여 부분적으로 고려될 수 있습니다.
둘째, 일부 오래된 기능은 하위 호환성을 제공하기가 간단합니다. Python 3.0 이전의 “고전 나눗셈” 동작을 고려해 보세요. python-future
프로젝트는 future.utils.old_div
함수에 고전 나눗셈의 호환 가능한 구현을 포함하고 있습니다.
def old_div(a, b):
"""
Equivalent to ``a / b`` on Python 2 without ``from __future__ import division``.
"""
if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral):
return a // b
else:
return a / b
이러한 함수를 적절한 __past__
호출 후에 a / b
의 모든 출현에 대해 호출하는 간단한 메커니즘과 함께 Python 3.x 버전에 번들링하는 것이 부담스럽지 않을 것입니다.
Q4: 성능은 어떻습니까? 레거시 기능의 무게로 인해 새로운 Python 버전의 성능이 저하되지 않을까요?
A4: 이는 경우에 따라 평가될 수 있습니다. 주요 잠재적 우려는 레거시 옵션의 존재 때문에 새로운 기본 동작의 성능이 부당하게 저하되지 않는다는 것입니다. __past__
호출의 영향 하에서의 성능은 부차적인 중요성을 가집니다.
저작권
이 문서는 퍼블릭 도메인에 공개되었습니다.
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments