PEP 829 – 패키지 시작 설정 파일
- Author:
- Barry Warsaw <barry at python.org>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Created:
- 31-Mar-2026
- Python-Version:
- 3.15
- Post-History:
- 01-Apr-2026, 13-Apr-2026, 15-Apr-2026
- Resolution:
- 24-Apr-2026
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 패키지가 Python의 시작 과정에 영향을 미치는 방식을 변경합니다. 지금까지는 인터프리터 시작 중에 site.py 파일이 파싱하고 실행하는 레거시 .pth 파일을 통해 이를 제어했으며, 이러한 파일은 사용자 코드의 첫 줄로 제어가 넘어가기 전에 sys.path를 확장하고 패키지 초기화 코드를 실행하는 데 사용됩니다.
이 PEP는 다음을 제안합니다:
.pth파일의import줄을.start파일의 진입점 명세(즉,pkg.mod:callable)로 대체합니다.- 일치하는
.start파일이 있으면 그와 일치하는.pth파일의import줄 처리가 비활성화됩니다. .pth파일의sys.path확장 기능은 유지됩니다.
.pth 파일의 import 줄 지원은 점진적으로 제거됩니다:
- 처음 3년 동안(Python 3.15, 3.16, 3.17이 될 것으로 예상됩니다)
.pth파일의import줄 처리는 유지되지만, 일치하는.start파일이 있는 경우는 예외입니다. - 그다음 2년 동안(Python 3.18과 3.19가 될 것으로 예상됩니다)
.pth파일의import줄은 아무런 알림 없이 무시됩니다. - 그 이후(Python 3.20 이상이 될 것으로 예상됩니다)에는
.pth파일에import줄이 존재하면 경고가 발생합니다.
동기
Python의 .pth 파일(시작 시 Lib/site.py가 처리합니다)은 다음 두 가지 함수(기능)를 지원합니다:
sys.path확장 – 이 파일의 줄(주석과import로 시작하는 줄 제외)은sys.path에 추가될 디렉터리를 지정합니다. 상대 경로는 암묵적으로 패키지가 설치되는 site-packages 디렉터리를 기준으로 합니다.- 임의 코드 실행 –
import(또는import\\t)로 시작하는 줄은 소스 문자열을exec()에 전달하여 즉시 실행됩니다.
두 기능 모두 타당한 사용 사례가 있지만, import 줄 기능이 가장 문제가 되는 이유는 다음과 같습니다:
- 코드 실행은 구현의 부수 효과입니다.
import로 시작하는 줄은 여러 문장을 세미콜론으로 구분하여 확장할 수 있습니다. 실행할 코드가 모두 같은 줄에 있기만 하면,.pth파일이 처리될 때 그 코드가 모두 실행됩니다. import줄은 인터프리터 시작 중에exec()를 사용하여 실행되므로 광범위한 공격 표면이 생깁니다.- Python 패키징에서 확립된 패턴인 진입점이라는 명시적인 개념이 없습니다. 시작 시 코드 실행과 초기화가 필요한 패키지는 진입점을 명시적으로 선언하는 대신
import줄을 남용합니다.
명세
이 PEP는 다음을 제안합니다:
<name>.pth파일 형식은 유지하되,import줄 처리는 3년 동안 폐지 예정으로 두고 그 이후에는 이러한 줄을 허용하지 않습니다.<name>.pth파일의 현재sys.path확장 기능은 변경 없이 유지합니다. 구체적으로, 절대 경로는 그대로 사용하고 상대 경로는.pth파일이 있는 디렉터리를 기준으로 합니다.pkgutil.resolve_name()인자의 “콜론 형식”을 따르는 진입점을 지정하는<name>.start라는 새 파일 형식이 추가됩니다.- 폐지 예고 기간에는
<name>.pth파일과 짝을 이루는<name>.start파일이 있으면<name>.pth파일의import줄을 실행하지 않고, 대신<name>.start파일의 진입점을 사용합니다. 이는 이 PEP를 지원하는 Python 버전과 지원하지 않는 이전 버전 모두에 걸쳐 사용할 수 있는 마이그레이션 경로를 제공합니다. 이 경우import줄에 대한 경고는 출력되지 않습니다.폐지 기간 동안, 일치하는
<name>.start파일이 없는<name>.pth파일에 대해서는 기존 처리 방식이 변경되지 않지만, Python에-v(verbose) 플래그가 주어지면import줄에 대한 경고가 출력됩니다.폐지 예고 기간이 끝나면 짝을 이루는
<name>.start파일이 있든 없든<name>.pth파일의import줄은 무시되고 경고가 발생합니다.구체적인 마이그레이션 지침은 교육 방법 절을 참조하십시오.
<name>.pth 파일과 <name>.start 파일은 모두 지금의 .pth 파일처럼 site.py 모듈이 처리합니다. 즉, -S로 site.py 처리를 비활성화하면 두 파일 모두 처리되지 않습니다.
site.py 시작 코드는 다음과 같은 명시적인 단계로 나뉩니다:
<name>.pth파일을 찾아(자세한 내용은 파일 이름 지정과 탐색 참조) 파일 이름의 알파벳순으로 정렬합니다.- 정렬된 순서대로
<name>.pth파일을 구문 분석하면서 모든 경로 확장의 전역 목록을 유지합니다. 이 목록은 먼저 파일 순서를, 그다음에는 항목이 나타나는 순서를 따릅니다. 중복 항목은 무시됩니다. - 폐지 예고 기간에는
<name>.pth파일에서 찾은import줄을 수집합니다. 이 줄들은<name>.start파일 탐색이 끝난 뒤에 처리됩니다. - 향후 확장: 경로 확장 목록에 전역 정책 필터를 적용합니다.
- 전역 목록에 유지된 순서대로 경로 확장을
sys.path에 추가합니다. - 모든
<name>.start파일을 찾아(자세한 내용은 파일 이름 지정과 탐색 참조) 파일 이름의 알파벳순으로 정렬합니다.앞서 탐색한
<name>.pth파일과 짝을 이루는<name>.start파일이 있으면, 짝이 되는<name>.pth파일의import줄을 모두 버립니다. 자세한 내용과 근거는 교육 방법 절을 참조하십시오. - 정렬된 순서대로
<name>.start파일을 구문 분석하면서 모든 진입점의 전역 목록을 유지합니다. 이 목록은 먼저 파일 순서를, 그다음에는 항목이 나타나는 순서를 따릅니다. 중복 항목은 무시되지 않습니다. - 향후 확장: 진입점 목록에 전역 정책 필터를 적용합니다.
- 목록에 유지된 순서대로 각 진입점을
pkgutil.resolve_name()으로 해석하여 호출 가능 객체를 얻습니다. 진입점은 인자 없이 호출하며, 반환값은 무엇이든 버립니다. 해석된 객체가 호출 가능한지는 호출하기 전에 검사하지 않습니다(따라서 호출할 때TypeError가 발생하면 보고됩니다).
<name>.pth 파일과 <name>.start 파일에서는 주석 줄(즉, 공백이 아닌 첫 문자가 #인 줄)과 빈 줄을 무시합니다. 그 밖의 구문 분석 오류가 발생하면 해당 줄을 무시합니다.
진입점 문법
pkgutil.resolve_name()은 진입점 명세를 호출 가능 객체로 해석합니다. 그러나 Python 3.14 이하에서 이 함수는 문서에 유사 정규 표현식으로 설명된 두 가지 형식을 받아들입니다:
W(.W)*- 콜론이 없는 형식W(.W)*:(W(.W)*)?- 호출 가능 객체 접미사를 선택적으로 붙이는 콜론 형식
이 PEP는 pkg.mod:callable 형식의 진입점만 허용하도록 제안하며, 호출 가능 객체를 반드시 지정하도록 요구합니다. 더 자세한 논의는 미해결 문제를 참조하십시오.
파일 이름 지정과 탐색
- 패키지는 선택적으로
<name>.pth및<name>.start형식의 파일을 0개 이상 설치할 수 있습니다.<name>접두사는 임의로 정할 수 있으며 패키지 이름과 일치하거나 서로 일치할 필요는 없습니다. 다만 다른 조건이 모두 같다면 명확성을 위해 패키지 이름과 일치시키는 것을 권장합니다. 인터프리터는 접두사에 어떠한 제약도 강제하지 않습니다. - 파일은 알파벳 순서로 처리됩니다.
<name>.start파일은 현재<name>.pth파일이 위치하는 것과 동일하게, 패키지가 설치되는 site-packages 디렉터리에 위치합니다.<name>.pth파일의 위치는 그대로 유지됩니다.<name>.start파일의 탐색 규칙은 현재<name>.pth파일의 탐색 규칙과 같습니다. 단일.문자로 시작하는 파일 이름(예:.start)과 OS 수준의 숨김 속성(UF_HIDDEN,FILE_ATTRIBUTE_HIDDEN)이 있는 파일은 제외됩니다.
오류 처리
파싱 중에 발생한 오류는 일반적으로 건너뛰며, Python에 -v (verbose) 플래그가 주어졌을 때만 보고됩니다. 현재의 .pth 파일과 달리, 오류가 발생해도 파일 전체의 처리가 중단되지 않습니다.
<name>.pth또는<name>.start파일을 열거나 읽을 수 없으면 해당 파일을 건너뛰고 다음 파일로 처리를 계속합니다.- 유효하지 않은 진입점 명세는 건너뜁니다.
실행 중에 발생한 오류는 sys.stderr에 출력되고 처리는 계속됩니다.
- 유효하지 않거나 존재하지 않는 경로를 가리키는
sys.path확장 디렉터리는 모두 무시되며, 다음 경로 항목으로 처리를 계속합니다. - 진입점을 실행하는 중에 발생한 예외는 출력되며, 다음 진입점으로 처리를 계속합니다.
인코딩
<name>.start 파일은 반드시 utf-8-sig, 즉 바이트 순서 표시(BOM)가 선택적으로 붙는 UTF-8로 인코딩해야 합니다.
<name>.pth 파일도 utf-8-sig로 인코딩하는 것이 바람직합니다. 현재는 <name>.pth 파일이 utf-8-sig로 인코딩되어 있지 않으면 현재 로케일로 대체하여 디코딩하지만, 이 PEP는 이 지원을 5년 동안 폐기 예정 상태로 두며, 그 이후에는 <name>.pth 파일도 반드시 utf-8-sig로 인코딩해야 합니다.
향후 개선 사항
.pth 및 .start 파일의 2단계 처리를 도입하면 향후 개선 사항을 구현할 수 있게 됩니다. 예를 들어 어떤 전역 사이트 정책을 적용하여 sys.path 확장과 진입점 실행을 모두 더 세밀하게 제어할 수 있습니다. 파싱 후에 여러 기준에 따라 경로 확장이나 진입점을 허용하거나 거부하는 정책을 적용하는 방식을 생각해 볼 수 있습니다. 그러한 기준으로는 확장을 지정하는 데 사용된 <name> 접두사, 경로 위치, 진입점이 정의된 모듈 등이 있습니다.
이 PEP는 이러한 정책 메커니즘의 설계를 의도적으로 향후 명세에 맡깁니다.
근거
이 PEP의 이전 버전은 메타데이터, 경로 확장 목록, 진입점 목록을 테이블로 지정하는 통합 <name>.site.toml 파일을 사용하도록 제안했습니다. PEP 작성자와 여러 논의 참가자는 이 구조화된 접근 방식을 좋아했지만, 여러 반대자는 이 제안에 TOML 파일이 과하다는 의견을 밝혔습니다. PEP 작성자는 TOML 파일의 처리 오버헤드가 무시할 만한 수준이었고, 구조화된 접근 방식이 가독성과 향후 확장성에 유용했다고 생각합니다. 반대자들은 YAGNI를 들어 반박했습니다.
두 파일 방식은 기존 .pth 파일 처리 방식을 단순하게 진화시킨 개선안입니다. 첫 번째 개선점은 import 줄을 exec()로 실행하는 임의 코드 실행 기능을 폐지하고 제거하는 것입니다. 이러한 줄은 광범위한 공격 벡터이며, exec()에 대한 표준 라이브러리 문서조차 이를 강력히 경고합니다. 이러한 줄을 모듈 내부의 진입점 함수를 호출하는 더 좁은 방식으로 대체하면 공격 벡터가 간접적으로 줄어듭니다. 사람과 자동 취약점 스캐너 모두 모듈 내부의 함수를 더 쉽게 감사할 수 있기 때문입니다.
두 번째 개선 사항은 sys.path 확장과 진입점 명세를 각각이 지원하는 정확한 사용 사례에 특화된 두 개의 파일로 분리하는 것입니다. 목적이 뒤섞이지 않고, 효과가 서로 얽힐 가능성도 없으며, 파일 형식은 더 읽기 쉽고, 처리 규칙은 명확합니다. sys.path 확장을 먼저 처리하여 모듈을 임포트할 수 있는 기반을 마련한 다음 진입점을 처리합니다. 어떤 파일 형식이 어떤 사용 사례를 지원하는지 모호함 없이 명확합니다.
세 번째 개선점은 이 파일들을 2단계로 처리하는 방식입니다. 파싱 오류를 일찍 보고할 수 있으며, 오류가 있더라도 각 파일의 나머지 줄 처리를 중단할 필요가 없습니다. sys.path 확장과 진입점 호출 모두에서 처리 단계와 실행 단계가 나뉘므로, site.py 처리를 완전히 비활성화하는 강경한 수단에 의존하지 않고도 어떤 경로 확장과 진입점을 허용할지(그리고 그에 따라 안전하다고 간주할지)를 명시적으로 제어하는 전역 정책을 (향후) 설계하고 구현할 기회가 생깁니다.
발견된 모든 <name>.pth 파일의 유효한 sys.path 확장은 <name>.start 파일의 진입점이 호출되기 전에 모두 처리됩니다. 이는 진입점 모듈을 임포트하는 데 필요한 모든 sys.path 수정 사항이 먼저 적용되도록 보장하기 위한 것입니다.
진입점은 같은 <name>.start 파일에 여러 번 정의되었든 둘 이상의 <name>.start 파일에 걸쳐 정의되었든 관계없이 중복 제거되지 않습니다. 즉, 진입점이 두 번 이상 나타나면 두 번 이상 호출됩니다. sys.path 항목의 중복 제거(sys.path에서 어떤 디렉터리 경로가 중복 항목보다 뒤에 나타나면 아무 효과가 없음)와 달리, 사용자가 – 가능성은 낮지만 – 실제로 진입점을 여러 번 호출하기를 원할 수도 있습니다. 이렇게 하면 독립적으로 작성된 <name>.start 파일들에 걸쳐 진입점 중복 제거 의미 체계를 정의해야 하는 복잡성도 피할 수 있습니다.
하위 호환성
이 PEP는 .pth 파일 내부의 import 줄 처리에 대해 3년의 폐지 예고 기간을 제안합니다. .pth 파일의 sys.path 확장은 변경되지 않습니다.
현재 .pth 파일의 import 줄 임의 코드 실행 기능을 사용하는 모든 패키지에는 항상 간단한 마이그레이션 전략이 있어야 합니다. 해당 코드를 패키지 내부의 임포트 가능한 모듈 안에 있는 호출 가능 객체로 옮긴 다음, <name>.start 파일 안의 진입점 명세에 이 호출 가능 객체의 이름을 지정하기만 하면 됩니다.
보안 영향
이 PEP는 인터프리터 시작 중의 코드 실행 경로를 더 쉽게 감사할 수 있게 합니다.
sys.path확장과 코드 실행을 별도의 두 파일로 분리하면 site-dir의 파일 목록만 보고도 임의 코드 실행이 정확히 어디에서 일어나는지 알 수 있습니다.exec()에 의한 임의 코드 실행을 제거하고, 더 제한적이고 감사 가능한 진입점 실행으로 대체합니다.- 진입점에 접근하고 실행하는 데 Python의 임포트 시스템이 사용되므로, 표준 감사 훅(PEP 578)으로 모니터링할 수 있습니다.
- 2단계 처리 모델은 향후 정책 메커니즘이 실행되는 내용을 검사하고 제한할 수 있는 자연스러운 훅을 만들어 냅니다.
package.module:callable문법은 실행 대상을 임포트 가능한 모듈 내의 호출 가능 객체로 제한합니다.
이 PEP로 시작 전 코드 실행 공격 표면 전체가 제거되지는 않습니다. 악의적인 패키지는 여전히 진입점을 통해 임의 코드를 실행할 수 있지만, 이 PEP에서 제안하는 메커니즘은 더 구조화되어 있고, 감사 가능하며, 향후 정책 제어를 적용하기에 더 적합합니다.
교육 방법
site 모듈 문서는 <name>.pth 및 <name>.start 파일의 동작과 모범 사례를 설명하도록 갱신될 것입니다. 패키지 작성자를 위한 다음 마이그레이션 지침이 포함될 것입니다:
- 패키지가 현재
<name>.pth파일을 제공하고 있다면, 그 파일을sys.path확장에 사용하는지 아니면 시작 시 코드 실행에 사용하는지 분석하십시오.sys.path확장 줄은 모두 그대로 유지할 수 있습니다. import줄의 코드 실행 기능을 사용하고 있다면, 패키지 안의 임포트 가능한 모듈에 (인자를 받지 않는) 호출 가능 객체를 만드십시오. 이것들을 대응하는<name>.start파일에pkg.mod:callable진입점으로 명시하십시오.- 패키지가 이 PEP를 지원하지 않는 이전 Python과 지원하는 새로운 Python 모두에 걸쳐 동작해야 한다면,
<name>.pth의import줄을 다음 형식으로 변경하십시오:import pkg.mod; pkg.mod.callable()이렇게 하면 이전 Python은 이
import줄을 실행하고, 새로운 Python은 이를 무시하고 대신<name>.start파일을 사용합니다. 두 경우 모두 사실상 같은 코드가 사용되므로, 약간의 중복이 있기는 하지만 그 정도는 최소한입니다. - 두 버전을 함께 지원하는 기간이 끝나면
<name>.pth파일에서import줄을 모두 제거하십시오.
규범적인 사항은 아니지만, 패키지에 <name>.pth 파일과 <name>.start 파일이 모두 포함되어 있고 전자에 후자의 줄과 일치하지 않는 import 줄이 있다면 빌드 도구가 경고를 내보내는 것이 좋을 수 있습니다.
참조 구현
참조 구현은 이 PEP의 현재 버전을 지원합니다.
기각된 아이디어
.pth파일에 진입점만 추가하고import줄은 그대로 두기- 이 방안은 의도가 뒤섞인다는 점과 앞서 설명한 마이그레이션 경로를 근거로 기각되었습니다. 관심사 분리 원칙에 따르면 패키지가 어떤 사용 사례를 활용하는지 쉽게 이해할 수 있습니다.
<name>.site.toml파일- 이것은 이 PEP의 이전 초안에서 제안된 통합된 새 파일 형식이었습니다. TOML 파일의 구조화된 형식은 과하며, TOML 파일을 파싱하는 오버헤드가 향후 확장성이라는 이점에 비해 가치가 없다는 의견이 대체로 우세했습니다.
- 패키지별 파일 대신 단일 설정 파일
- 사이트 전체에 걸친 단일 설정 파일도 검토했으나, 독립적으로 설치된 패키지 간의 조율이 필요하고 도구들이 이미 이해하고 있는
<package>.pth관례를 반영하지 못하기 때문에 거부되었습니다. - 처리 순서를 위한 우선순위 또는 가중치 필드
- 패키지는 독립적으로 설치되므로 우선순위를 결정할 주체가 없습니다. 알파벳 순서는 현재의
<name>.pth처리 순서와 일치합니다. 우선순위는 패키지별 메타데이터가 아니라 향후 도입될 사이트 전체 정책 설정 파일로 다룰 수 있습니다. - 호출 가능 객체에 인자 전달하기
- 단순성을 위해, 그리고 진입점에 전달할 만한 명백히 유용한 인자가 없기 때문에 호출 가능 객체는 인자 없이 호출됩니다.
미해결 문제
- 진입점 문법 절에서 설명했듯이, 이 PEP는
pkgutil.resolve_name()이 구현하는 허용 가능한 객체 참조 문법을 좁게 정의하여 사용할 것을, 즉 구체적으로pkg.mod:callable문법을 요구할 것을 제안합니다. 이는 직접적인 임포트 부수 효과(즉, 모듈 스코프 수준의 기능)를 통한 코드 실행을 권장하고 싶지 않기 때문입니다.이 제한이 받아들여진다고 가정하더라도, 이를 어떻게 구현할지는 미해결 문제입니다.
site.py가 이를 직접 강제할 수도 있지만, 그렇게 하면pkgutil.resolve_name()을 사용하는 목적이 다소 무색해집니다. PEP 작성자가 선호하는 방식은pkgutil.resolve_name()에 선택적 키워드 전용 인자, 즉 하위 호환성을 위해 기본값이False인strict를 추가하는 것입니다.strict=True는 허용 가능한 입력을 사실상W(.W)*:(W(.W)*)로 좁힙니다. 즉, 콜론이 없는 이전 형식을 거부하고 콜론 뒤의 호출 가능 객체를 필수로 만듭니다. site.addpackage()는 단일.pth파일을 처리하는 문서화되지 않은 함수입니다. 이 함수는site.__all__에 나열되어 있지 않고, Doc/library/site.rst에서도 다루지 않으며, 안정성도 보장되지 않습니다. GitHub 코드 검색 결과, 이 함수를 직접 호출하는 서드파티 프로젝트가 대략 여섯 개 정도 발견되었으며 대부분site.addpackage(dir, "apps.pth", set())패턴을 사용했습니다 — 이들은 모두site.addsitedir(dir)로 대체할 수 있습니다.참조 구현 작업 과정에서
addpackage()는.pth및.start파일을 처리하는 새로운 내부 파이프라인을 감싸는 얇은 래퍼가 됩니다. 이를 별도의 함수로 유지하면 문서화된 사용 사례도 없이 복잡성만 늘어납니다. 이 함수는 폐지 예정(deprecated)으로 지정하고, 사용자에게 대신 문서화된 공개 API인addsitedir()로 마이그레이션하도록 안내해야 합니다.- 현재 이 PEP는
.pth파일의import줄 처리에 대해 3년의 폐지 예정 기간을 권장합니다. 일치하는.start파일이 있으면 폐지 예정 기간 동안.pth파일의import줄에 대한 경고가 비활성화되므로, 패키지는 경고 없이 두 방식을 모두 지원할 수 있습니다. 그러나 현재 작성된 내용대로라면 폐지 예정 기간이 끝날 때 경고가 다시 활성화되므로, 그 시점부터는 경고 없이 두 방식을 모두 지원할 방법이 없습니다.선호하는 해결책은
.pth파일의import줄에 대한 모든 경고를 그저-v(verbose) 플래그 뒤로 숨기는 것으로, 이를 5년 전체 기간 동안(3년의 처리 폐지 예정 일정은 유지) 적용하거나 무기한 적용하는 것입니다. - 향후
-X옵션이 오류 보고나 진입점 실행에 대한 세밀한 제어를 제공해야 할까요? - 이 PEP는 이름이 비슷하더라도 목적과 동작이 완전히 다르기 때문에
._pth파일의 사용은 다루지 않습니다.
변경 이력
19-Apr-2026
<name>.start및<name>.pth파일의 인코딩 요구 사항에 대한 설명을 추가했습니다.- 마이그레이션 지침을 갱신했습니다.
- 폐지 예정 기간 동안, 일치하는
<name>.start파일이 없는<name>.pth파일의import줄에 대한 경고는-v(verbose) 옵션이 주어진 경우에만 발생합니다. - 일치하는
<name>.start파일이 있는<name>.pth파일의import줄은 무시된다는 점을 명확히 했습니다. site.addpackage()폐지 예정, 그리고-v옵션이 주어지지 않는 한.pth파일의import줄 경고를 억제하는 기간을 2년 더 연장하는 것과 관련된 몇 가지 미해결 문제를 추가했습니다.
- PEP 제목을 변경했습니다.
- 이 PEP는 더 이상
Packaging토픽에 속하지 않습니다. - 이제 이 PEP는
<name>.pth파일 형식의 발전과 진입점 명세를 위한<name>.start파일의 추가를 제안합니다. 이전 버전의<name>.site.toml파일은 제거되었습니다. .pth파일의import줄에 대해 3년의 폐지 예정 기간을 제안합니다.
감사의 글
PEP 작성자는 이 제안이 첫 초안에서 현재 형태에 이르는 절충안으로 이어진 건설적이고 즐거운 대화에 대해 Paul Moore에게 감사드립니다. 피드백과 격려를 보내 준 Emma Smith와 Brett Cannon에게도 감사드립니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.