setuptools, wheel, PyPI를 활용한 Python 프로젝트 배포 간소화
Olivia Novak
Dev Intern · Leapcell

소개
견고한 Python 애플리케이션을 개발하는 것은 여정의 한 부분일 뿐이며, 이를 다른 사람들에게 접근 가능하고 쉽게 설치할 수 있도록 만드는 것 또한 똑같이 중요합니다. 훌륭한 유틸리티를 만들었지만 사용자들이 수동 종속성 관리 및 복잡한 설정 절차로 어려움을 겪는다고 상상해 보세요. 이것이 표준화된 패키징 및 배포가 작동하는 방식이며, 당신의 프로젝트를 스크립트 모음에서 전문적으로 배포 가능한 패키지로 변환합니다.
광대한 Python 생태계에서 setuptools
, wheel
을 사용하고 PyPI를 통해 배포하는 기술을 익히는 것은 모범 사례일 뿐만 아니라, 당신의 작업을 원활하게 공유, 협업 및 더 넓게 채택할 수 있도록 하는 근본적인 기술입니다. 이 글은 이러한 도구의 복잡성을 파헤쳐, 원시 프로젝트에서 공개적으로 사용 가능하고 설치 가능한 Python 패키지로 가는 과정을 안내할 것입니다.
시작하기 전 핵심 개념
실제적인 측면을 자세히 살펴보기 전에, 관련된 주요 플레이어에 대한 공통된 이해를 확립합시다.
setuptools
: 이것은 Python 패키지 생성의 초석입니다.distutils
(Python의 표준 배포 유틸리티)의 기능을 확장하여 Python 패키지를 정의, 빌드 및 설치하기 위한 강력한 도구를 제공하는 라이브러리입니다. 메타데이터 및 종속성 지정부터 배포 아카이브 생성까지 모든 것을 처리합니다.wheel
: 휠 (.whl
파일)은 Python을 위한 사전 빌드된 배포 형식입니다. 소스 배포 (sdist)와 달리 휠에는 컴파일된 바이트코드가 포함되어 있으며 설정 스크립트 실행이나 확장 컴파일 없이 직접 설치할 준비가 되어 있습니다. 이를 통해 설치 속도가 크게 향상되고 일반적인 환경 관련 문제를 피할 수 있어 많은 사람들이 선호하는 배포 형식입니다.- PyPI (Python Package Index): "파이-파이-아이"로 발음되며, Python의 공식 타사 소프트웨어 저장소입니다. Python 개발자가 패키지를 업로드하고 사용자가
pip
와 같은 도구를 사용하여 다운로드 및 설치할 수 있는 방대한 공개 인덱스입니다. Python 소프트웨어의 중앙 시장이라고 생각하시면 됩니다. pip
: Python의 패키지 설치 프로그램입니다. 패키징에 직접적으로 관여하지는 않지만,pip
는 사용자가 PyPI 또는 다른 소스에서 당신의 패키지를 설치할 때 사용할 주요 도구입니다.pip
가 당신의 배포된 패키지와 상호 작용하는 방식을 이해하는 것이 필수적입니다.
Python 프로젝트 패키징 및 배포
Python 프로젝트를 패키징하고 배포하는 과정은 일반적으로 프로젝트 메타데이터 정의, 배포 아카이브 생성, 그리고 해당 아카이브를 PyPI에 업로드하는 것을 포함합니다. 각 단계를 실제 예시와 함께 자세히 살펴보겠습니다.
1. 프로젝트 구조
잘 구성된 프로젝트 구조는 첫 번째 단계입니다. my_package
라는 간단한 프로젝트를 고려해 봅시다.
my_package_project/
├── my_package/
│ ├── __init__.py
│ └── main.py
├── tests/
│ ├── test_main.py
├── README.md
├── LICENSE
└── setup.py
여기서 my_package/
는 실제 Python 패키지 디렉터리이고, tests/
에는 테스트가 포함되어 있으며, README.md
는 프로젝트 문서를 제공하고, LICENSE
는 라이선스 정보를 지정하며, setup.py
는 패키징 노력의 핵심입니다.
2. setup.py
로 프로젝트 메타데이터 정의
setup.py
파일은 setuptools.setup()
을 사용하여 프로젝트에 대한 모든 필수 정보를 정의하는 곳입니다. my_package
에 대한 기본 setup.py
를 만들어 봅시다.
# setup.py from setuptools import setup, find_packages setup( name='my_package', version='0.1.0', description='A simple example Python package', long_description=open('README.md').read(), long_description_content_type='text/markdown', author='Your Name', author_email='your.email@example.com', url='https://github.com/yourusername/my_package', packages=find_packages(), # Automatically finds all packages in the directory classifiers=[ 'Programming Language :: Python :: 3', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', ], python_requires='>=3.6', install_requires=[ # List your project's dependencies here # 'requests>=2.20.0', # 'numpy', ], entry_points={ 'console_scripts': [ 'my-package-cli=my_package.main:cli_entry_point', ], }, )
필드 설명:
name
: 패키지 이름입니다. 사용자가 설치할 때 입력하는 것 (예:pip install my_package
)입니다.version
: 패키지의 현재 버전 (예:0.1.0
)입니다. 명확성을 위해 Semantic Versioning을 따르세요.description
: 짧고 한 줄짜리 요약입니다.long_description
: 종종README.md
에서 읽어오는 상세한 설명입니다.long_description_content_type
:long_description
의 형식을 지정합니다 (예:text/markdown
).author
,author_email
: 귀하의 연락처 정보입니다.url
: 프로젝트 홈페이지 또는 GitHub 저장소입니다.packages
: 이것이 중요합니다.find_packages()
는 프로젝트 내의 모든 Python 패키지 (__init__.py
가 있는 디렉터리)를 자동으로 검색합니다. 수동으로 나열하는 것도 옵션입니다.classifiers
: PyPI에서 프로젝트를 분류하여 사용자가 찾도록 돕습니다. 포괄적인 목록은 PyPI에서 확인할 수 있습니다.python_requires
: 필요한 최소 Python 버전을 지정합니다.install_requires
: 패키지가 필요로 하는 런타임 종속성을 나열합니다.pip
는 패키지가 설치될 때 이러한 종속성을 자동으로 설치합니다.entry_points
: 패키지가 명령행 스크립트를 제공하는 경우 여기에 정의합니다.my-package-cli
는my_package.main
의cli_entry_point
함수를 실행하는 호출 가능한 명령이 됩니다.
my_package/main.py
에는 다음과 같은 내용이 있을 수 있습니다.
# my_package/main.py def cli_entry_point(): print("Hello from my_package CLI!") if __name__ == '__main__': cli_entry_point()
3. 소스 및 휠 배포 빌드
setup.py
가 준비되면 배포 아카이브를 빌드할 수 있습니다. 먼저 build
가 설치되어 있는지 확인하십시오: pip install build
.
터미널에서 프로젝트의 루트 디렉터리 (my_package_project/
)로 이동하여 다음을 실행하십시오.
python -m build
이 명령은 일반적으로 새로 생성된 dist/
디렉터리 안에 두 가지 유형의 배포 파일을 생성합니다.
- 소스 배포 (sdist): 소스 코드와
setup.py
를 포함하는.tar.gz
파일입니다. 처음부터 빌드하려는 사용자용입니다. - 휠 배포 (bdist_wheel):
.whl
파일입니다. 이는 사전 빌드되어 즉시 설치 가능한 패키지로, 컴파일된 확장 프로그램이 포함된 경우 플랫폼별이거나 (플랫폼에 구애받지 않는) "순수 Python"입니다. 이를 통해 설치 속도가 크게 향상되고 일반적인 환경 관련 문제를 피할 수 있습니다.
간단한 my_package
의 경우 다음과 같은 파일이 보일 수 있습니다.
dist/
├── my_package-0.1.0-py3-none-any.whl # Wheel
└── my_package-0.1.0.tar.gz # Source distribution
휠 파일 이름 my_package-0.1.0-py3-none-any.whl
은 일반적으로 다음을 나타냅니다: package_name-version-python_tag-abi_tag-platform_tag.whl
. py3-none-any
는 Python 3와 호환되고, 특정 ABI (Application Binary Interface)가 없으며, 플랫폼에 구애받지 않음을 나타냅니다.
4. PyPI에 업로드
배포 파일이 준비되면 공개 릴리스의 마지막 단계는 PyPI에 업로드하는 것입니다.
a. PyPI 및 TestPyPI에 등록
먼저 두 곳 모두에 계정이 필요합니다.
b. twine
설치
twine
은 PyPI에 패키지를 안전하게 업로드하는 것이 권장되는 유틸리티입니다. 설치하십시오.
pip install twine
c. TestPyPI에 업로드 (권장!)
항상 TestPyPI를 사용하여 업로드 프로세스를 먼저 테스트하십시오. 이는 실제 릴리스를 만들기 전에 문제를 포착하는 데 도움이 됩니다.
twine upload --repository testpypi dist/*
TestPyPI 사용자 이름과 비밀번호 (보안상 TestPyPI 계정 설정에서 생성된 API 토큰)를 입력하라는 메시지가 표시됩니다.
성공적인 업로드 후, test.pypi.org/project/my_package
에서 패키지를 확인할 수 있습니다. 심지어 설치할 수도 있습니다.
pip install --index-url https://test.pypi.org/simple/ --no-deps my_package
--no-deps
플래그는 TestPyPI 자체에서 잘못되거나 오래된 종속성을 설치하는 것을 피하기 위해 TestPyPI 업로드에 유용한 경우가 많습니다.
d. 공식 PyPI에 업로드
TestPyPI 업로드에 확신이 서면 공식 PyPI에 업로드할 수 있습니다.
twine upload dist/*
다시 말하지만, PyPI 사용자 이름과 API 토큰을 입력합니다.
축하합니다! 이제 패키지가 PyPI에 올라갔으며 누구나 pip install my_package
를 사용하여 설치할 수 있습니다.
응용 시나리오
- 오픈 소스 라이브러리: 재사용 가능한 코드를 전 세계와 공유하여 쉽게 검색 및 설치할 수 있도록 합니다.
- 내부 회사 도구: 수동 설치 단계 없이 독점 유틸리티 또는 모듈을 조직 내에 배포합니다.
- 복잡한 애플리케이션: 주 배포가 PyPI를 통하지 않더라도 패키징을 이해하면 안정적인 종속성 관리 및 잠재적 미래 PyPI 릴리스를 위해 프로젝트를 구성하는 데 도움이 됩니다.
- 종속성 관리:
install_requires
를 올바르게 정의함으로써 사용자가 추측할 필요 없이 모든 필요한 구성 요소를 얻도록 보장합니다.
결론
setuptools
, wheel
, PyPI를 사용하여 Python 프로젝트를 패키징하고 배포하는 것은 모든 진지한 Python 개발자에게 필수적인 기술입니다. 이는 당신의 원시 코드를 전문적이고 쉽게 공유 가능하며 설치 가능한 제품으로 변환합니다. 이러한 단계를 따르면 당신의 노력이 대상 고객에게 원활하게 도달하여 Python 커뮤니티 내에서 더 넓은 채택과 협업을 촉진할 수 있습니다. 이 워크플로우를 마스터하고 당신의 Python 창작물의 잠재력을 최대한 발휘하십시오.