PEP 727 – Annotated 메타데이터 안의 문서화
- Author:
- Sebastián Ramírez <tiangolo at gmail.com>
- Sponsor:
- Jelle Zijlstra <jelle.zijlstra at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Withdrawn
- Type:
- Standards Track
- Topic:
- Typing
- Created:
- 28-Aug-2023
- Python-Version:
- 3.13
- Post-History:
- 30-Aug-2023
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 새 클래스 typing.Doc을 사용하여 Annotated로 정의한 Python 심볼에 문서화 문자열을 제공하는 표준화된 방법을 제안합니다.
PEP 철회
이 PEP에 대한 반응은 대체로 부정적이었으며, 장황함과 가독성에 대한 우려가 제기되었습니다. 그 결과, 이 PEP는 철회되었습니다.
동기
클래스, 함수, 클래스 메서드, 모듈에 문서를 제공하는 방법은 이미 잘 정의되어 있습니다. 바로 독스트링을 사용하는 것입니다.
현재 매개변수, 반환값, 클래스 범위 변수(클래스 변수와 인스턴스 변수), 지역 변수, 타입 별칭 같은 다른 종류의 심볼에 문서화 문자열을 제공하는 공식화된 표준은 없습니다.
그럼에도 불구하고 이러한 추가 심볼 대부분을 문서화할 수 있도록 독스트링 안의 마이크로문법 형태로 여러 관례가 만들어졌으며, 현재 널리 사용되고 있습니다. Sphinx, numpydoc, Google, Keras 등이 그 예입니다.
도구가 이러한 관례를 지원하게 되는 상황은 두 가지입니다. 하나는 작성자가 문서화 문자열의 내용을 편집하는 동안이고, 다른 하나는 사용자를 위해 그 내용을 어떤 방식으로 렌더링하는 동안(문서 사이트, 편집기의 툴팁 등)입니다.
이러한 관례는 각각 문자열 안의 마이크로문법을 사용하기 때문에, 해당 독스트링을 편집할 때 편집기가 자동 완성이나 잘못된 문법에 대한 인라인 오류 표시 등을 쉽게 지원할 수 없습니다. 이러한 관례에 대한 편집 지원은 어떤 종류든 표준 Python 문법 편집 지원 위에 별도로 추가되어야 합니다.
현재 관례로 매개변수를 문서화할 때는 독스트링이 코드에서 실제 매개변수와 다른 위치에 있고 정보(매개변수 이름)를 중복해서 적어야 하므로, 매개변수에 대한 정보가 실제 매개변수 선언에서 상당히 멀리 떨어진 곳에 놓이기 쉽고 선언과 분리됩니다. 이 때문에 함수를 리팩터링하면서 매개변수를 제거하고 그 문서는 제거하는 것을 잊어버리기 쉽습니다. 새 매개변수를 추가할 때도 마찬가지입니다. 그 매개변수에 대한 독스트링을 추가하는 것을 잊어버리기 쉽습니다.
또한 이와 같은 정보(매개변수 이름)의 중복 때문에, 편집기와 기타 도구는 시그니처와 독스트링에 있는 매개변수의 일관성을 검사하거나 보장하기 위해 복잡한 맞춤 로직이 필요하며, 그렇지 않으면 이를 온전히 지원하지 못합니다.
이러한 기존 관례는 문자열 안에 들어 있는 서로 다른 종류의 마이크로문법이므로, 렌더링을 위해 이를 견고하게 파싱하려면 이를 지원하는 도구가 복잡한 로직을 구현해야 합니다. 게다가 라이브러리와 도구는 특정 독스트링 관례 파서에 의존하지 않고서는 런타임에 개별 매개변수나 변수의 문서를 얻을 간단한 방법이 없습니다. 런타임에 매개변수 문서화 문자열에 접근할 수 있다면 유용할 것입니다. 예를 들어 각 매개변수 문서의 내용을 테스트하거나, 비슷한 여러 함수 간의 일관성을 보장하거나, 같은 매개변수 문서를 다른 방식으로 추출하여 노출하는 데(예: FastAPI를 사용한 API, Typer를 사용한 CLI 등) 활용할 수 있습니다.
이전 형식 중 일부는 이전 Python 버전에 타입 어노테이션이 없다는 점을 보완하기 위해 독스트링에 타입 정보를 포함하려고 했습니다(예: Sphinx, numpydoc). 그러나 이제는 공식적인 타입 어노테이션 문법이 있으므로 그 정보를 독스트링에 둘 필요가 없습니다.
근거
이 제안은 독스트링의 정보를 확장하고 보완하며, 기존 독스트링과의 하위 호환성을 유지하고(독스트링을 폐기하지 않습니다), Annotated를 사용한 타입 어노테이션과 typing의 새 클래스 Doc을 통해 Python 언어와 구조를 활용하는 방식으로 이러한 단점을 해결하고자 합니다.
이것이 외부 패키지가 아니라 Python 표준 라이브러리에 속해야 하는 이유는, 구현 자체는 매우 간단하겠지만 실제 효용과 이점은 표준이 된다는 데서 나오기 때문입니다. 표준이 되면 라이브러리 작성자가 더 쉽게 사용할 수 있고, Annotated를 사용해 Python 심볼을 문서화하는 기본 방법을 제공할 수 있습니다. 일부 도구 제공자(최소한 VS Code와 PyCharm)는 이것이 표준이 될 경우에만 지원 구현을 고려하겠다는 입장을 보였습니다.
이 제안은 현재의 독스트링 사용을 폐기하지 않으며, 독스트링을 사용할 수 있는 경우에는 독스트링을 우선적인 문서화 방법으로 간주해야 합니다(타입 별칭, 매개변수 등에서는 사용할 수 없습니다). 그리고 Annotated로 선언할 수 있는 심볼에 특화된 문서화(현재는 여러 마이크로문법 관례로만 다루어지고 있습니다)에 대해서는 이 제안이 독스트링을 보완하게 됩니다.
이 제안을 채택한 라이브러리의 소스 파일을 직접 열어 보지 않는 한, 일반 개발자(라이브러리 사용자)에게는 비교적 드러나지 않을 것입니다.
이 제안은 채택하려는 라이브러리 작성자가 선택적으로 사용하는 것으로 간주되어야 하며, 라이브러리 작성자는 사용 여부를 자유롭게 결정할 수 있어야 합니다.
이 제안은 선택적 타입 힌트를 기꺼이 사용하려는 라이브러리에만 유용합니다.
요약
현재 관례와 대비되는 이 제안의 특징을 간단히 요약하면 다음과 같습니다.
- 편집은 Python 문법을 지원하는 모든 편집기(현재 또는 미래의 편집기)에서 문법 오류, 구문 강조 등을 포함하여 기본적으로 이미 완전히 지원됩니다.
- 렌더링은 정적 도구(런타임 실행이 필요 없는 도구)로 비교적 간단하게 구현할 수 있습니다. 해당 정보는 이러한 도구가 보통 이미 생성하는 AST에서 추출할 수 있기 때문입니다.
- 정보 중복 제거: 매개변수 이름이 독스트링 안에 중복되지 않고 한 곳에서만 정의됩니다.
- 매개변수나 클래스 변수를 제거하면서 그 문서를 제거하는 것을 잊어 불일치가 생길 가능성을 없앱니다.
- 새 매개변수나 클래스 변수를 추가하면서 그 문서를 추가하는 것을 잊을 가능성을 최소화합니다.
- 매개변수 이름을 바꿀 때 시그니처의 매개변수 이름과 독스트링의 이름 사이에 불일치가 생길 가능성을 없앱니다.
- 기존(이전) Python 버전을 포함하여, 런타임에 각 심볼의 문서화 문자열에 접근할 수 있습니다.
- 타입 별칭처럼
Annotated를 사용할 수 있는 다른 심볼을 문서화하는 더 형식화된 방법을 제공합니다. - 새로 시작하는 사람이 배워야 할 마이크로 문법이 없습니다. 그냥 Python 문법입니다.
ParamSpec에 의해 포착된 함수에 대해 매개변수 문서 상속을 지원합니다.
명세
주요 제안은 새 클래스 typing.Doc을 도입하는 것입니다. 이 클래스는 Annotated 어노테이션 안에서만 사용해야 합니다. 이 클래스는 위치 전용 문자열 인자 하나를 받습니다. 이 클래스는 Annotated를 사용하여 선언된 심볼의 의도된 의미와 용도를 문서화하는 데 사용해야 합니다.
예를 들면 다음과 같습니다.
from typing import Annotated, Doc
class User:
name: Annotated[str, Doc("The user's name")]
age: Annotated[int, Doc("The user's age")]
...
Annotated는 보통 타입 어노테이션으로 사용되며, 그런 경우 그 안에 있는 모든 typing.Doc은 어노테이션이 달린 심볼을 문서화합니다.
Annotated가 타입 별칭을 선언하는 데 사용될 때는 typing.Doc이 타입 별칭 심볼을 문서화합니다.
예를 들면 다음과 같습니다.
from typing import Annotated, Doc, TypeAlias
from external_library import UserResolver
CurrentUser: TypeAlias = Annotated[str, Doc("The current system user"), UserResolver()]
def create_user(name: Annotated[str, Doc("The user's name")]): ...
def delete_user(name: Annotated[str, Doc("The user to delete")]): ...
이 경우 사용자가 CurrentUser를 임포트했다면, 편집기 같은 도구는 사용자가 그 심볼 위에 마우스를 올렸을 때 문서화 문자열이 담긴 툴팁을 제공할 수 있고, 문서화 도구는 생성하는 결과물에 타입 별칭과 그 문서를 함께 포함할 수 있습니다.
런타임에 정보를 추출하는 도구는 보통 get_type_hints()를 include_extras=True 매개변수와 함께 사용할 것이며, Annotated는 (타입 별칭을 사용하더라도) 정규화되므로, typing.Doc이 둘 이상 사용된 경우에는 마지막으로 사용된 것이므로 사용 가능한 마지막 typing.Doc을 사용해야 한다는 뜻입니다.
런타임에 typing.Doc 인스턴스는 전달된 문자열을 담은 documentation 속성을 가집니다.
함수의 시그니처가 ParamSpec에 의해 포착될 때, 매개변수와 연관된 모든 문서화 문자열은 유지되어야 합니다.
typing.Doc 객체를 처리하는 모든 도구는 해당 문자열을 독스트링으로 해석해야 하며, 따라서 inspect.cleandoc()을 사용한 것처럼 공백을 정규화해야 합니다.
typing.Doc에 전달되는 문자열은 유효한 독스트링이 될 수 있는 형태여야 합니다. 즉, f-strings와 문자열 연산을 사용해서는 안 됩니다. 이는 Python 런타임이 강제할 수 없으므로, 도구는 이 동작에 의존해서는 안 됩니다.
렌더링을 제공하는 도구가 원시 시그니처를 보여 줄 때, 원시 Annotated 코드 전체를 표시할지 설정할 수 있게 할 수 있지만, 기본적으로는 Annotated와 그 내부 코드 메타데이터를 포함하지 않고 어노테이션이 달린 심볼의 타입만 표시해야 합니다. 그러한 도구가 typing.Doc과 원시 시그니처 이외의 다른 방식의 렌더링을 지원할 때는, typing.Doc에 전달된 문자열 값을 문서화된 심볼과 문서화 문자열 사이의 관계가 드러나는 편리한 방식으로 보여 주어야 합니다.
렌더링을 제공하는 도구는 매개변수 문서와 서술형 독스트링을 어디에 보여 줄지 다양한 방식으로 설정할 수 있게 할 수 있습니다. 그렇지 않다면, 단순히 서술형 독스트링을 먼저 보여 주고 매개변수 문서를 그다음에 보여 줄 수 있습니다.
예시
클래스 속성을 문서화할 수 있습니다:
from typing import Annotated, Doc
class User:
name: Annotated[str, Doc("The user's name")]
age: Annotated[int, Doc("The user's age")]
...
함수나 메서드의 매개변수와 반환값도 마찬가지입니다:
from typing import Annotated, Doc
def create_user(
name: Annotated[str, Doc("The user's name")],
age: Annotated[int, Doc("The user's age")],
cursor: DatabaseConnection | None = None,
) -> Annotated[User, Doc("The created user after saving in the database")]:
"""Create a new user in the system.
It needs the database connection to be already initialized.
"""
pass
하위 호환성
이 제안은 기존 코드와 완전히 하위 호환되며, 독스트링 규약의 기존 사용 방식을 폐기하지 않습니다.
표준 라이브러리에서 사용할 수 있게 되기 전에 이를 도입하려는 개발자나 이전 버전의 Python을 지원하려는 개발자는 typing_extensions를 사용하여 그곳에서 Doc을 임포트해 사용할 수 있습니다.
예를 들면 다음과 같습니다:
from typing import Annotated
from typing_extensions import Doc
class User:
name: Annotated[str, Doc("The user's name")]
age: Annotated[int, Doc("The user's age")]
...
보안 영향
알려진 보안 영향은 없습니다.
교육 방법
문서화의 주된 수단은 계속해서 서술형 정보를 위한 표준 독스트링이어야 하며, 이는 모듈, 클래스, 함수, 메서드에 적용됩니다.
이 제안을 도입하여 더 세분화된 문서를 추가하려는 작성자는 이를 지원하는 심볼에 대해 Annotated 어노테이션 안에서 typing.Doc을 사용할 수 있습니다.
이전 버전의 Python과의 하위 호환성을 유지하면서 이 제안을 도입하려는 라이브러리 작성자는 typing.Doc 대신 typing_extensions.Doc을 사용해야 합니다.
참조 구현
typing.Doc은 다음과 동등하게 구현됩니다:
class Doc:
def __init__(self, documentation: str, /):
self.documentation = documentation
이는 typing_extensions 패키지에 구현되어 있습니다.
다른 언어 조사
다음은 다른 언어들이 심볼을 어떻게 문서화하는지에 대한 간략한 조사입니다.
Java
Java 함수와 그 매개변수는 함수 정의 위에 작성하는 특수한 형식의 주석인 Javadoc으로 문서화됩니다. 이는 Python의 현재 독스트링 마이크로문법 규약과 비슷합니다(다만 하나뿐입니다).
예를 들면 다음과 같습니다:
/**
* Returns an Image object that can then be painted on the screen.
* The url argument must specify an absolute <a href="#{@link}">{@link URL}</a>. The name
* argument is a specifier that is relative to the url argument.
* <p>
* This method always returns immediately, whether or not the
* image exists. When this applet attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives
* that draw the image will incrementally paint on the screen.
*
* @param url an absolute URL giving the base location of the image
* @param name the location of the image, relative to the url argument
* @return the image at the specified URL
* @see Image
*/
public Image getImage(URL url, String name) {
try {
return getImage(new URL(url, name));
} catch (MalformedURLException e) {
return null;
}
}
JavaScript
JavaScript와 TypeScript는 모두 Javadoc과 비슷한 시스템을 사용합니다.
JavaScript는 JSDoc을 사용합니다.
예를 들면 다음과 같습니다:
/**
* Represents a book.
* @constructor
* @param {string} title - The title of the book.
* @param {string} author - The author of the book.
*/
function Book(title, author) {
}
TypeScript
TypeScript에는 약간의 차이가 있는 자체 JSDoc 참조가 있습니다.
예를 들면 다음과 같습니다:
// Parameters may be declared in a variety of syntactic forms
/**
* @param {string} p1 - A string param.
* @param {string=} p2 - An optional param (Google Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @returns {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4) {
// TODO
}
Rust
Rust는 Doc 주석에서 마이크로문법의 또 다른 비슷한 변형을 사용합니다.
하지만 순수한 Markdown에서 추론할 수 있는 것 외에는, 어떤 문서가 어떤 심볼/매개변수를 가리키는지 나타내는 특별히 잘 정의된 마이크로문법 구조가 없습니다.
예를 들면 다음과 같습니다:
#![crate_name = "doc"]
/// A human being is represented here
pub struct Person {
/// A person must have a name, no matter how much Juliet may hate it
name: String,
}
impl Person {
/// Returns a person with the name given them
///
/// # Arguments
///
/// * `name` - A string slice that holds the name of the person
///
/// # Examples
///
/// ```
/// // You can have rust code between fences inside the comments
/// // If you pass --test to `rustdoc`, it will even test it for you!
/// use doc::Person;
/// let person = Person::new("name");
/// ```
pub fn new(name: &str) -> Person {
Person {
name: name.to_string(),
}
}
/// Gives a friendly hello!
///
/// Says "Hello, [name](Person::name)" to the `Person` it is called on.
pub fn hello(& self) {
println!("Hello, {}!", self.name);
}
}
fn main() {
let john = Person::new("John");
john.hello();
}
Go 언어
Go도 Doc Comments의 한 형태를 사용합니다.
어떤 문서가 어떤 심볼/매개변수를 가리키는지 나타내는 잘 정의된 마이크로문법 구조는 없지만, 매개변수는 특별한 문법이나 표시 없이 이름으로 참조할 수 있습니다. 이는 문서 텍스트에 등장할 수 있는 일반적인 단어를 매개변수 이름으로 사용하지 않아야 한다는 뜻이기도 합니다.
package strconv
// Quote returns a double-quoted Go string literal representing s.
// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
// for control characters and non-printable characters as defined by IsPrint.
func Quote(s string) string {
...
}
기각된 아이디어
현재의 독스트링 표준화
가능한 대안 중 하나는 기존 독스트링 형식 중 하나를 지원하고 이를 표준으로 추진하는 것입니다. 하지만 이는 표준화 문제만 해결할 뿐입니다.
이 방식은 순수 Python 문법 대신 독스트링 안에서 마이크로 문법을 사용하는 데서 비롯되는 다른 문제는 하나도 해결하지 못합니다. 이는 위의 근거 - 요약에서 설명한 것과 같습니다.
추가 메타데이터와 데코레이터
이 제안 이전의 몇몇 아이디어에는 단일 클래스 Doc 대신, 객체의 사용이 권장되지 않는지, 어떤 예외를 발생시킬 수 있는지 등을 나타내는 여러 매개변수를 가진 함수 doc()을 두는 방안이 포함되어 있었습니다. 함수와 클래스의 폐기(deprecation)도 가능하도록 doc()을 데코레이터로 사용할 수 있을 것으로도 예상했습니다. 하지만 이 기능은 PEP 702의 typing.deprecated()가 다루고 있으므로, 이 제안에서는 제외되었습니다.
추가 정보를 선언하는 방법은 앞으로도 여전히 유용할 수 있지만, 이 아이디어에 대한 초기 피드백을 반영하여 그 모든 것을 향후 제안으로 미루었습니다.
이로 인해 초점도 여러 매개변수를 가진 포괄적인 함수 doc()에서, 향후 다른 제안과 조합할 수 있는 방식으로 Annotated 안에서 사용되는 단일 Doc 클래스로 옮겨 갔습니다.
이러한 설계 변경은 typing.deprecated() 같은 다른 제안과의 상호 운용성도 향상시킵니다. 향후에는 개별 매개변수를 폐기하기 위해 typing.deprecated()를 Annotated 안에서도 사용할 수 있도록 하여 Doc과 공존하게 하는 방안을 고려할 수 있기 때문입니다.
정의 아래의 문자열
논의에서 제안된 대안 중 하나는 심볼의 정의 아래에 문자열을 선언하고 그 값에 대한 런타임 접근을 제공하는 것입니다:
class User:
name: str
"The user's name"
age: int
"The user's age"
...
이는 이미 PEP 224에서 제안되었다가 기각되었는데, 주된 이유는 문자열이 자신이 문서화하는 심볼과 어떻게 연결되는지가 모호하다는 점이었습니다.
또한 이전 버전의 Python에서는 런타임에 이 값에 접근할 방법을 제공할 수 없습니다.
Annotated 안의 일반 문자열
논의에서는 Annotated 안에 일반 문자열을 사용하자는 제안도 있었습니다:
from typing import Annotated
class User:
name: Annotated[str, "The user's name"]
age: Annotated[int, "The user's age"]
...
하지만 이렇게 하면 Annotated 안의 모든 일반 문자열에 미리 정해진 의미가 생기게 되며, 현재 허용되는 방식대로 그 안의 일반 문자열을 다른 목적으로 사용하던 도구는 모두 유효하지 않게 됩니다.
명시적인 typing.Doc을 두면 현재 유효한 Annotated 사용 방식과 호환됩니다.
Annotated와 유사한 또 다른 타입
논의에서는 Annotated와 유사한 새로운 타입을 정의하자는 제안도 있었는데, 이 타입은 타입과 문서 문자열을 담은 매개변수를 받게 됩니다:
from typing import Doc
class User:
name: Doc[str, "The user's name"]
age: Doc[int, "The user's age"]
...
이 아이디어는 해당 사용 사례만 지원하고, 다른 목적(예: FastAPI 메타데이터, Pydantic 필드 등)으로 Annotated와 결합하거나 문서화 문자열 외에 추가 메타데이터(예: 폐지)를 덧붙이기가 더 어려워지므로 거부되었습니다.
타입 별칭에서 문서 전달하기
이 제안의 이전 버전에서는 Annotated로 선언된 타입 별칭이 사용되고 그 타입 별칭이 어노테이션에 사용될 때, 문서 문자열이 어노테이션된 심볼로 전달된다고 명시했습니다.
예를 들면 다음과 같습니다:
from typing import Annotated, Doc, TypeAlias
UserName: TypeAlias = Annotated[str, Doc("The user's name")]
def create_user(name: UserName): ...
def delete_user(name: UserName): ...
이 방식은 에디터 지원을 제공하는 데 쓰이는 주요 구성 요소 중 하나의 유지 관리자에게서 피드백을 받은 뒤 거부되었습니다.
슬라이스를 이용한 축약 표기
논의에서는 슬라이스를 이용한 축약 표기를 사용하자는 제안도 있었습니다:
is_approved: Annotated[str: "The status of a PEP."]
매우 영리한 아이디어이고 새로운 Doc 클래스가 필요 없어지기는 하지만, 현재 버전의 Python 런타임 실행 방식에서는 이를 허용하지 않습니다.
런타임에 Annotated는 최소 두 개의 인자를 요구하고 첫 번째 인자가 타입이어야 하므로, 첫 번째 인자가 슬라이스이면 오류가 발생합니다.
미해결 문제
장황함
이에 반대하는 주된 인자는 장황함이 늘어난다는 점입니다.
시그니처를 문서화와 분리해서 보지 않고 독스트링을 포함한 함수 본문까지 함께 측정한다면, 전체적인 장황함은 대체로 비슷할 것입니다. 이 제안이 하는 일은 본문에 있는 독스트링의 내용 일부를 시그니처로 옮기는 것이기 때문입니다.
본문 없이 시그니처만 놓고 보면, 시그니처는 지금보다 훨씬 길어질 수 있으며 한 페이지를 넘게 될 수도 있습니다. 그 대신, 현재 한 페이지를 넘는 그에 상응하는 독스트링은 훨씬 짧아질 것입니다.
시그니처와 독스트링을 포함한 전체적인 장황함을 비교하면, 이 제안으로 인해 추가되는 주된 장황함은 Annotated와 typing.Doc을 사용하는 데서 비롯될 것입니다. Annotated가 더 많이 사용된다면, 이것과 이것이 담는 메타데이터 유형을 위해 개선된 더 짧은 문법을 마련하는 것이 합리적일 수 있습니다. 하지만 그것은 Annotated가 더 널리 사용된 뒤에야 의미가 있을 것입니다.
한편, 최종 사용자는 typing.Doc을 사용하는 내부 코드를 보지 않으므로 이러한 장황함의 영향을 받지 않을 것입니다. 대다수의 사용자는 내부를 들여다보지 않고 편집기를 통해 라이브러리와 상호 작용할 것이며, 오히려 이 제안을 지원하는 편집기에서 툴팁을 얻게 될 것입니다.
늘어난 장황함을 감당하는 비용은 주로 이 기능을 사용하는 라이브러리 유지 관리자가 부담하게 됩니다.
이 인자는 일반적인 타입 어노테이션에 반대하는 인자와 유사하다고 볼 수 있습니다. 타입 어노테이션도 그 기능을 제공하는 대가로 실제로 장황함을 늘리기 때문입니다. 하지만 다시 말하지만, 타입 어노테이션과 마찬가지로 이는 선택 사항이며, 이점을 얻는 대가로 추가적인 장황함을 기꺼이 감수하려는 사람들만 사용하게 될 것입니다.
물론 더 숙련된 사용자는 라이브러리의 소스 코드를 살펴보고 싶을 수 있으며, 해당 라이브러리의 작성자가 이를 도입했다면 그러한 숙련된 사용자는 독스트링의 장황함 대신 시그니처의 장황함이 추가된 코드를 보게 될 것입니다.
이를 도입하지 않기로 결정한 작성자는 자신이 정한 어떤 형식의 독스트링이든 계속 사용하거나, 독스트링을 전혀 쓰지 않는 등 자유롭게 선택할 수 있어야 합니다.
그럼에도 이것이 공인된 해결책이 된다면 라이브러리 작성자들이 이를 도입하라는 압력을 받을 가능성이 높습니다.
문서화는 타이핑이 아닙니다
문서화는 사실 타이핑의 일부가 아니라거나, 다른 모듈에 있어야 한다는 주장도 있을 수 있습니다. 또는 이 정보가 시그니처의 일부가 아니라 (독스트링처럼) 다른 곳에 있어야 한다는 주장도 있을 수 있습니다.
그럼에도 Python의 타입 어노테이션은 이미 기본적으로 추가 메타데이터라고 볼 수 있습니다. 타입 어노테이션은 변수, 매개변수, 반환 타입에 대한 추가 정보를 담고 있으며, 기본적으로 런타임 동작이 없습니다. 그리고 이 제안은 여기에 메타데이터 유형을 하나 더 추가하는 것입니다.
PEP 702가 타입 어노테이션을 확장하여 폐지 예정 정보를 포함하도록 한 것과 마찬가지로, 이 제안은 타입 어노테이션이 담는 정보의 유형을 확장하는 것이라고 볼 수 있습니다.
Annotated는 바로 어노테이션에 추가 메타데이터를 덧붙일 수 있도록 표준 라이브러리에 추가되었으며, 새로 제안된 Doc 클래스는 Annotated와 긴밀하게 결합되어 있으므로 같은 모듈에 두는 것이 합리적입니다. Annotated가 다른 모듈로 옮겨진다면, Doc도 함께 옮기는 것이 합리적일 것입니다.
여러 표준
이에 반대하는 또 다른 인자는 이것이 또 하나의 표준을 만들게 되며, 독스트링에 관한 관례가 이미 여러 가지 존재한다는 점입니다. 현재 존재하는 표준 중 하나를 공식화하는 편이 더 나아 보일 수도 있습니다.
그렇지만 앞서 언급했듯이, 그러한 관례 중 어느 것도 이 제안이 자연스럽게 해결하는 독스트링 기반 접근 방식의 일반적인 단점을 다루지 못합니다.
독스트링 기반 접근 방식의 단점 목록은 앞의 근거 - 요약 절을 참고하십시오.
마찬가지로, 새로운 기능을 활용하고 이전 방식의 여러 문제를 해결하는 새 표준은 많은 경우 도입할 가치가 있다고 볼 수 있습니다. 새로운 pyproject.toml, dataclass_transform, 새로운 타이핑 파이프/유니언(|) 연산자를 비롯한 여러 사례가 그러합니다.
채택
이것은 새로운 표준 제안이므로, 커뮤니티의 관심이 있을 때에만 의미가 있습니다.
다행히 FastAPI, Typer, SQLModel, Asyncer(이 제안의 작성자가 만든 라이브러리), Pydantic, Strawberry(GraphQL) 등 여러 개발자와 팀이 만든 여러 주요 라이브러리에서 이미 관심을 보이고 있습니다.
mkdocstrings 같은 문서화 도구에서도 관심과 지지를 보이고 있으며, 이 도구는 이 제안의 이전 버전에 대한 지원까지 추가했습니다.
초기 피드백을 위해 연락한 CPython 코어 개발자 모두(최소 4명)가 이 제안에 관심과 지지를 보였습니다.
편집기 개발자(VS Code와 PyCharm)는 어느 정도 관심을 보이면서 제안의 시그니처가 장황하다는 점에 우려를 표했지만, 그들에게 가장 큰 영향을 미칠 부분인 구현에 대해서는 우려를 표하지 않았습니다. 또한 이것이 공식 표준이 된다면 이에 대한 지원 추가를 검토하겠다는 뜻을 밝혔습니다. 그 경우 에디터 개발자는 렌더링 지원만 추가하면 됩니다. 다른 표준에서는 보통 존재하지 않는 편집 지원은 이미 갖추어져 있는데, 표준 Python 문법의 편집을 이미 지원하기 때문입니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.