Python 패키징의 기본이었던 setup.py, 이제는 바뀌어야 할 때

Python 프로젝트에서 패키지를 만들 때 우리는 자연스럽게 setup.py를 작성해왔다.
하지만 어느 순간부터 공식 문서와 최신 패키지 관리 도구들은 setup.py 대신 pyproject.toml을 사용하라고 권장하고 있다.

기존 방식도 문제없이 잘 사용하고 있었는데, 왜 바꾸라는 걸까?
사실 setup.py에는 패키징을 어렵게 만드는 여러 단점이 존재했고, 이를 해결하기 위해 새로운 표준이 등장했다.


setup.py, 대체 뭐가 문제였을까?

기존 setup.py 방식은 오랫동안 Python 패키징의 기본이었다.
보통 다음과 같이 작성해서 패키지를 관리했다.

from setuptools import setup, find_packages

setup(
    name="my_package",
    version="0.1.0",
    packages=find_packages(),
    install_requires=[
        "numpy",
        "requests",
    ],
)

익숙하고 직관적인 방식이지만, 문제점이 없던 건 아니다.

setup.py의 문제점

  • 패키징을 위한 의존성을 명확하게 정의할 방법이 없었다
    • 패키지를 빌드할 때 필요한 도구(setuptools, wheel 등)를 명시적으로 정의할 수 없었다.
    • 빌드 환경이 바뀔 때마다 pip install setuptools wheel을 직접 실행해야 했다.
  • 실행 방식이 환경마다 달라질 가능성이 있었다
    • setup.py는 Python 코드로 실행되기 때문에, 환경에 따라 다르게 동작할 수 있었다.
    • 예를 들어, install_requires를 동적으로 구성하면 패키지를 설치하는 머신마다 결과가 달라질 수도 있었다.
  • 일관되지 않은 빌드 방식
    • setup.py를 실행하면 패키지를 설치할 수도 있고, 빌드할 수도 있었지만, 특정 방식이 강제되지 않았다.
    • python setup.py install, pip install ., python setup.py bdist_wheel 등 여러 방식이 혼재하면서 패키징 과정이 복잡해졌다.

이런 문제를 해결하기 위해 등장한 것이 바로 pyproject.toml 이다.


이제는 pyproject.toml이 표준이다

Python 패키징 관련 PEP(PEP 517, PEP 518)에서 pyproject.toml패키징의 새로운 표준으로 정의했다.
이제 setup.py는 더 이상 공식적으로 권장되지 않으며, pyproject.toml을 사용해야 한다.

pyproject.toml의 장점

  • 빌드 시스템을 명확히 정의할 수 있다
    • 패키지를 빌드할 때 필요한 도구(setuptools, wheel 등)를 명확하게 지정할 수 있다.
    • pip install .을 실행하면 자동으로 빌드 도구가 설치되므로 별도의 설정이 필요 없다.
    [build-system]
    requires = ["setuptools", "wheel"]
    build-backend = "setuptools.build_meta"
  • 설정이 정적으로 관리된다
    • setup.py처럼 실행 시점에 동적으로 변경되지 않고, 항상 동일한 방식으로 패키징된다.
    • 덕분에 설치 결과가 일관되며, 환경에 따른 예외 상황이 줄어든다.
    [project]
    name = "my_package"
    version = "0.1.0"
    dependencies = [
        "numpy",
        "requests"
    ]
  • 보다 현대적인 패키지 관리 방식과 호환된다
    • poetry, hatch, pip-tools 같은 최신 패키지 관리 도구는 pyproject.toml을 기본적으로 지원한다.
    • pip install도 이제는 pyproject.toml 기반으로 동작하도록 최적화되었다.

setup.py 대신 pyproject.toml을 어떻게 사용해야 할까?

기존 setup.py를 다음과 같이 변환하면 된다.

기존 setup.py 방식

from setuptools import setup, find_packages

setup(
    name="my_package",
    version="0.1.0",
    packages=find_packages(),
    install_requires=[
        "numpy",
        "requests",
    ],
)

권장되는 pyproject.toml 방식

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my_package"
version = "0.1.0"
dependencies = [
    "numpy",
    "requests"
]

이제 패키지를 설치할 때는 setup.py 없이도 다음 명령어로 간단하게 설치할 수 있다.

pip install .

빌드도 python setup.py가 아닌 다음 명령어로 실행하면 된다.

pip install build
python -m build

결론: 이제는 pyproject.toml을 써야 한다

오랫동안 사용해온 setup.py 방식은 이제 공식적으로 권장되지 않는다.
그동안 별 문제 없이 사용해왔던 방식이지만, 사실 여러 단점이 있었고, 이를 해결하기 위해 pyproject.toml이 등장했다.

특히, 최신 Python 패키징 도구들은 모두 pyproject.toml을 기반으로 동작하므로, setup.py를 계속 고집하기보다는 새로운 방식으로 전환하는 것이 장기적으로 유리하다.
기존 프로젝트에서도 pyproject.toml을 도입하는 것이 점점 필수가 되어가고 있으므로, 더 늦기 전에 익숙해지는 것이 좋겠다.

Profile

한창헌

https://github.com/HanChangHun