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

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 새로운 클래스 typing.Doc을 사용하여 Annotated로 정의된 Python 기호에 대한 문서 문자열을 제공하는 표준화된 방법을 제안합니다.

PEP 철회

이 PEP에 대한 반응은 대체로 부정적이었으며, 장황함과 가독성에 대한 우려가 제기되었습니다. 그 결과 이 PEP는 철회되었습니다.

동기

클래스, 함수, 클래스 메서드 및 모듈에 문서를 제공하는 잘 정의된 방법은 이미 존재합니다. 바로 독스트링을 사용하는 것입니다.

현재 매개변수, 반환 값, 클래스 범위 변수(클래스 변수 및 인스턴스 변수), 지역 변수 및 타입 별칭과 같은 다른 유형의 기호에 문서 문자열을 제공하기 위한 공식 표준은 없습니다.

그럼에도 불구하고 이러한 추가 기호 대부분을 문서화할 수 있도록 독스트링 내부에 마이크로 구문으로 사용되는 여러 규칙이 만들어졌으며, 현재 널리 사용되고 있습니다. Sphinx, numpydoc, Google, Keras 등이 그 예입니다.

이러한 규칙이 도구에서 지원되는 시나리오는 두 가지입니다. 작성자의 경우 문서 문자열의 내용을 editing할 때이고, 사용자의 경우 해당 내용을 어떤 방식으로든 rendering할 때입니다(문서 사이트, 편집기의 툴팁 등).

이러한 각 규칙은 문자열 내부에서 마이크로 구문을 사용하므로, editing하는 독스트링에 대해 편집기가 자동 완성이나 잘못된 구문에 대한 인라인 오류 등을 쉽게 지원할 수 없습니다. 이러한 규칙에 대한 모든 유형의 editing지원은 표준 Python 구문 편집 지원 위에 추가로 제공되어야 합니다.

현재 규칙으로 매개변수를 문서화할 때는 독스트링이 실제 매개변수와 코드상 다른 위치에 있고 정보(매개변수 이름)를 중복해야 하므로, 매개변수에 관한 정보가 실제 매개변수 선언에서 상당히 멀리 떨어진 코드 위치에 놓이기 쉽고 서로 연결되지 않습니다. 따라서 함수를 리팩터링하여 매개변수를 제거한 뒤 해당 매개변수의 문서를 제거하는 것을 잊기 쉽습니다. 새 매개변수를 추가할 때도 마찬가지로 해당 매개변수의 독스트링을 추가하는 것을 잊기 쉽습니다.

또한 이와 같은 정보(매개변수 이름)의 중복 때문에 편집기와 기타 도구는 시그니처와 독스트링에 있는 매개변수의 일관성을 검사하거나 보장하기 위해 복잡한 사용자 지정 로직이 필요하며, 그렇지 않으면 이를 완전히 지원하지 못합니다.

이러한 기존 규칙은 문자열 내부에 있는 서로 다른 유형의 마이크로 구문이므로, 이를 rendering하기 위해 견고하게 구문 분석하려면 해당 규칙을 지원하는 도구에 복잡한 로직을 구현해야 합니다. 또한 특정 독스트링 규칙 분석기에 의존하지 않고는 라이브러리와 도구가 런타임에 각 개별 매개변수나 변수의 문서를 얻을 수 있는 간단한 방법이 없습니다. 런타임에 매개변수 문서 문자열에 접근할 수 있다면 각 매개변수 문서의 내용을 테스트하거나, 여러 유사 함수 간의 일관성을 보장하거나, 동일한 매개변수 문서를 다른 방식으로 추출하여 노출하는 데 유용할 것입니다(예: FastAPI를 사용한 API, Typer를 사용한 CLI 등).

이러한 이전 형식 중 일부는 독스트링에 타입 정보를 포함하여 이전 Python 버전에서 타입 어노테이션이 부족한 문제를 해결하려 했습니다(예: Sphinx, numpydoc). 그러나 이제 타입 어노테이션을 위한 공식 syntax for type annotations가 있으므로 해당 정보는 독스트링에 포함할 필요가 없습니다.

근거

이 제안은 기존 독스트링의 하위 호환성을 유지하면서(기존 독스트링을 폐기하지 않음) 독스트링의 정보를 확장하고 보완하여 이러한 단점을 해결하고자 합니다. 또한 Annotated를 사용한 타입 어노테이션과 typing의 새로운 클래스 Doc을 통해 Python 언어와 구조를 활용하는 방식으로 이를 수행합니다.

이것이 외부 패키지가 아니라 표준 Python 라이브러리에 속해야 하는 이유는 구현 자체는 매우 간단하더라도, 실제 힘과 이점은 표준으로 제공되는 데서 비롯되기 때문입니다. 이를 통해 라이브러리 작성자가 쉽게 사용할 수 있고, Annotated를 사용하여 Python 기호를 문서화하는 기본 방법을 제공할 수 있습니다. 일부 도구 제공업체(최소한 VS Code와 PyCharm)는 이것이 표준인 경우에만 지원 구현을 고려하겠다고 밝혔습니다.

이는 독스트링의 현재 사용을 폐기하지 않으며, 독스트링은 사용 가능한 경우(타입 별칭, 매개변수 등에서는 사용할 수 없음) 선호되는 문서화 방법으로 간주해야 합니다. 그리고 Annotated를 사용하여 선언할 수 있는 기호에 특화된 문서화(현재는 사용 가능한 여러 마이크로 구문 규칙으로만 다뤄짐)에 대해서는 이 제안이 독스트링을 보완하게 됩니다.

이 방식을 채택한 라이브러리의 소스 파일을 직접 열어 보지 않는 한 일반 개발자(라이브러리 사용자)에게는 비교적 투명할 것입니다.

이를 채택하려는 라이브러리 작성자에게 선택 사항으로 간주해야 하며, 사용할지 여부를 자유롭게 결정할 수 있어야 합니다.

선택적 타입 힌트를 사용할 의향이 있는 라이브러리에만 유용할 것입니다.

요약

다음은 현재 규칙과 대비한 이 제안의 기능을 간략히 요약한 것입니다.

  • Python 구문을 지원하는 모든 편집기(현재 또는 미래의 편집기)는 구문 오류, 구문 강조 등을 포함하여 Editing을 이미 기본적으로 완전히 지원합니다.
  • 렌더링은 정적 도구(런타임 실행이 필요하지 않은 도구)를 사용하여 비교적 간단하게 구현할 수 있습니다. 해당 정보는 이러한 도구가 일반적으로 이미 생성하는 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를 임포트하면, 편집기와 같은 도구는 사용자가 해당 심볼 위에 마우스를 올렸을 때 문서 문자열이 포함된 툴팁을 제공할 수 있으며, 문서화 도구는 생성된 출력에 해당 문서와 함께 타입 별칭을 포함할 수 있습니다.

런타임에 정보를 추출하는 도구는 일반적으로 매개변수 include_extras=True와 함께 get_type_hints()를 사용합니다. 또한 타입 별칭을 포함하여 Annotated가 정규화되므로, 둘 이상이 사용된 경우 마지막으로 사용 가능한 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 {
   ...
}

거부된 아이디어

현재 문서 문자열 표준화

가능한 대안은 기존 문서 문자열 형식 중 하나를 지원하고 표준으로 추진하는 것입니다. 그러나 이는 표준화 문제만 해결할 뿐입니다.

위의 Rationale - Summary에서 설명한 것과 마찬가지로, 순수 Python 구문 대신 문서 문자열 내부에서 마이크로 구문을 사용함으로써 발생하는 다른 문제는 해결하지 못합니다.

추가 메타데이터와 데코레이터

이 제안 이전의 일부 아이디어에는 단일 Doc 클래스 대신 여러 매개변수를 사용하는 doc() 함수가 포함되어 있었습니다. 이 함수는 객체의 사용을 권장하지 않는지, 어떤 예외를 발생시킬 수 있는지 등을 나타내기 위한 것입니다. 함수와 클래스를 더 이상 사용하지 않도록 지정할 수 있도록 doc()을 데코레이터로 사용할 수도 있을 것으로 예상했습니다. 그러나 이 기능은 PEP 702typing.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는 최소 두 개의 인자를 요구하며, 첫 번째 인자가 타입이어야 하므로 슬라이스이면 충돌합니다.

미해결 문제

장황함

이에 반대하는 주요 주장은 장황함이 증가한다는 것입니다.

시그니처를 문서와 독립적으로 보지 않고 독스트링이 포함된 함수 본문도 함께 측정한다면, 이 제안은 본문의 독스트링에서 일부 내용을 시그니처로 옮기는 것이므로 전체적인 장황함은 어느 정도 비슷할 것입니다.

본문을 제외하고 시그니처만 고려하면 현재보다 훨씬 길어질 수 있으며, 한 페이지를 넘길 수도 있습니다. 그 대신 현재 한 페이지를 넘기는 동일한 내용의 독스트링은 훨씬 짧아질 것입니다.

시그니처와 독스트링을 포함한 전체적인 장황함을 비교하면, 여기서 추가되는 주요 장황함은 Annotatedtyping.Doc를 사용하는 데서 비롯됩니다. 관련 Annotated가 더 널리 사용된다면, 이를 위한 문법과 이것이 담을 메타데이터 유형을 위한 문법을 개선하여 더 짧게 만드는 것이 합리적일 수 있습니다. 그러나 이는 Annotated가 더 널리 사용된 후에야 의미가 있을 것입니다.

반면 이러한 장황함은 최종 사용자에게 영향을 주지 않을 것입니다. 최종 사용자는 typing.Doc를 사용하는 내부 코드를 보지 않기 때문입니다. 대부분의 사용자는 내부를 살펴보지 않고 편집기를 통해 라이브러리와 상호 작용하며, 그렇지 않더라도 이 제안을 지원하는 편집기에서 도구 설명을 보게 될 것입니다.

추가적인 장황함을 처리하는 비용은 주로 이 기능을 사용하는 라이브러리 유지 관리자들이 부담하게 될 것입니다.

이 주장은 일반적으로 타입 어노테이션에 반대하는 주장과 유사할 수 있습니다. 타입 어노테이션은 기능을 제공하는 대신 실제로 장황함을 증가시키기 때문입니다. 그러나 타입 어노테이션과 마찬가지로 이는 선택 사항이며, 이점에 대한 대가로 추가적인 장황함을 감수할 의향이 있는 사람들만 사용하게 될 것입니다.

물론 고급 사용자일수록 라이브러리의 소스 코드를 살펴보고 싶어 할 수 있으며, 해당 라이브러리의 작성자가 이를 채택한다면 이러한 고급 사용자들은 독스트링의 장황함 대신 추가적인 시그니처의 장황함이 포함된 코드를 살펴보게 될 것입니다.

이를 채택하지 않기로 결정한 작성자는 자신이 원하는 특정 형식의 독스트링을 계속 사용하거나, 독스트링을 전혀 사용하지 않는 등의 선택을 자유롭게 할 수 있어야 합니다.

그럼에도 이것이 공식적으로 승인된 해결책이 된다면 라이브러리 작성자들이 이를 채택하라는 압력을 받을 가능성이 높습니다.

문서화는 타이핑이 아닙니다

문서화는 실제로 타이핑의 일부가 아니거나, 다른 모듈에 있어야 한다고 주장할 수도 있습니다. 또는 이 정보가 시그니처의 일부가 아니라 독스트링과 같은 다른 위치에 있어야 한다고 주장할 수도 있습니다.

그럼에도 Python의 타입 어노테이션은 기본적으로 이미 추가적인 메타데이터로 간주할 수 있습니다. 타입 어노테이션은 변수, 매개변수, 반환 타입에 관한 추가 정보를 전달하며 기본적으로 런타임 동작을 하지 않습니다. 그리고 이 제안은 타입 어노테이션에 메타데이터 유형을 하나 더 추가할 것입니다.

이 제안은 타입 어노테이션이 전달하는 정보의 유형을 확장한다고 주장할 수 있으며, 이는 PEP 702가 폐기 정보를 포함하도록 확장한 것과 같은 방식입니다.

Annotated는 어노테이션에 추가적인 메타데이터를 추가할 수 있도록 지원하기 위해 정확히 표준 라이브러리에 추가되었으며, 새로 제안된 Doc 클래스는 Annotated와 긴밀하게 결합되어 있으므로 동일한 모듈에 두는 것이 합리적입니다. 관련 Annotated를 다른 모듈로 옮긴다면, Doc도 함께 옮기는 것이 합리적입니다.

여러 표준

이에 반대하는 또 다른 주장은 이것이 또 하나의 표준을 만들게 되며, 독스트링에 관한 관례가 이미 여러 가지 존재한다는 것입니다. 현재 존재하는 표준 중 하나를 공식화하는 편이 더 나아 보일 수도 있습니다.

그럼에도 위에서 언급했듯이, 그러한 관례 중 어느 것도 이 제안이 자연스럽게 해결하는 독스트링 기반 접근 방식의 일반적인 단점을 다루지 못합니다.

독스트링 기반 접근 방식의 단점 목록을 보려면 위의 Rationale - Summary섹션을 참조하십시오.

이와 마찬가지로, 많은 경우 새로운 기능을 활용하고 이전 방식의 여러 문제를 해결하는 새로운 표준은 도입할 가치가 있다고 볼 수 있습니다. 새로운 pyproject.toml, dataclass_transform, 새로운 타이핑 파이프/합집합(|) 연산자 및 기타 사례의 경우가 그러합니다.

도입

새로운 표준 제안이므로, 커뮤니티의 관심을 받는 경우에만 의미가 있습니다.

다행히도 FastAPI, Typer, SQLModel, Asyncer(이 제안의 작성자가 개발함), Pydantic, Strawberry(GraphQL) 및 기타 여러 개발자와 팀이 개발한 주요 라이브러리에서 이미 관심을 보이고 있습니다.

또한 제안의 이전 버전에도 지원을 추가한 mkdocstrings와 같은 문서화 도구에서도 관심과 지원을 보이고 있습니다.

조기 피드백을 위해 연락한 모든 CPython 핵심 개발자(최소 4명)가 이 제안에 관심과 지지를 보였습니다.

편집기 개발자(VS Code 및 PyCharm)도 어느 정도 관심을 보였으며, 제안의 시그니처가 지나치게 장황하다는 우려를 나타냈지만, 구현에 대해서는 우려를 나타내지 않았습니다(구현이 그들에게 가장 큰 영향을 미칠 부분입니다). 또한 이 제안이 공식 표준이 된다면 지원 기능을 추가하는 방안을 검토하겠다고 밝혔습니다. 이 경우 렌더링 지원만 추가하면 됩니다. 다른 표준에서는 일반적으로 존재하지 않는 편집 지원은 이미 제공되고 있기 때문이며, 해당 편집기들이 이미 표준 Python 구문 편집을 지원하기 때문입니다.