[pyproject.toml 완전 정복 7편] 실제 프로젝트 예제 종합 실습

이번 글에서는 가상의 "my_project"라는 패키지를 예로 들어 pyproject.toml 작성을 단계별로 시연합니다. 목표는 다음과 같습니다.

  • 빌드 백엔드: Poetry 선택 (의존성 관리, 빌드, 배포 편의성 활용)
  • 기본 메타데이터: 이름, 버전, 저자, 라이선스 등 명시
  • 의존성: 런타임 의존성(예: requests), optional-dependencies(dev, docs) 정의
  • 스크립트 정의: mytool 명령어 제공
  • 린터/포매터 설정: black, mypy 설정 추가 (tool 섹션 활용)

프로젝트 디렉토리 구성

예제 디렉토리 구조:

my_project/
  ├─ my_project/
  │    ├─ __init__.py
  │    └─ cli.py
  ├─ pyproject.toml
  └─ README.md

my_project/cli.pymain() 함수 구현(간단히):

def main():
    print("Hello from my_project CLI!")

1단계: 기본 빌드 시스템 및 메타데이터 설정

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[project]
name = "my_project"
version = "0.1.0"
description = "A sample Python project using pyproject.toml"
readme = "README.md"
license = "MIT"
authors = [
  {name="Alice", email="alice@example.com"}
]
classifiers = [
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License"
]

dependencies = [
  "requests>=2.26.0,<3.0.0"
]

[project.scripts]
mytool = "my_project.cli:main"

여기까지 설정으로, Poetry 빌드 백엔드 사용, 프로젝트 이름/버전/저자/라이선스/클래시파이어 지정, requests 의존성, mytool 스크립트 정의 완료.

2단계: optional-dependencies로 dev, docs 그룹 설정

[project.optional-dependencies]
dev = [
  "pytest",
  "mypy",
  "black"
]
docs = [
  "sphinx"
]

이로써 pip install .[dev] 또는 poetry install --with dev 명령으로 개발용 도구 일괄 설치, docs 그룹 선택적 설치 가능.

3단계: 도구 설정 ([tool.*] 섹션)

Black, mypy 설정을 pyproject.toml에 통합:

[tool.black]
line-length = 88

[tool.mypy]
strict = true
disallow_untyped_defs = true

이렇게 하면 black, mypy 실행 시 pyproject.toml에서 설정을 읽어들여 통일된 환경 제공.

만약 Poetry 추가 설정(예: 릴리즈 전략) 필요시 tool.poetry 섹션 활용 가능:

[tool.poetry]
# 여기서 name, version 등 project 정보 대신 project 섹션을 사용하는 것이 권장되나,
# Poetry 구버전 호환성 고려 시 tool.poetry에 메타데이터를 둘 수도 있음.

(단, PEP 621 채택 이후는 [project] 섹션 사용을 권장하므로 이 예제에서는 [tool.poetry] 섹션 최소화)

최종 pyproject.toml 예제

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[project]
name = "my_project"
version = "0.1.0"
description = "A sample Python project using pyproject.toml"
readme = "README.md"
license = "MIT"
authors = [{name="Alice", email="alice@example.com"}]
classifiers = [
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License",
]
dependencies = [
  "requests>=2.26.0,<3.0.0"
]
scripts = { mytool = "my_project.cli:main" }

[project.optional-dependencies]
dev = ["pytest", "mypy", "black"]
docs = ["sphinx"]

[tool.black]
line-length = 88

[tool.mypy]
strict = true
disallow_untyped_defs = true

빌드 및 확인

Poetry 설치 후:

pip install poetry
poetry install
poetry run mytool  # "Hello from my_project CLI!" 출력
poetry run mypy my_project
poetry run black my_project

추가로 poetry build 명령으로 wheel 빌드, poetry publish로 PyPI 업로드 가능(테스트 PyPI에서 실험 권장).

결론

  • 실제 예제 프로젝트를 통해 [build-system], [project], [project.optional-dependencies], [project.scripts], [tool.*] 섹션을 종합적으로 구성하는 방법 시연
  • 빌드 백엔드(여기서는 Poetry) 선택, 의존성/스크립트/도구 설정을 한 곳에서 관리하며, 현대적이고 일관적인 패키징·빌드·개발 환경 확보
  • CI/CD, 배포 파이프라인, 개발자 온보딩 시에도 이 점이 큰 강점

다음 글에서는 기존 setup.py/requirements.txt 방식에서 pyproject.toml 기반 구조로 마이그레이션할 때의 전략, 베스트 프랙티스, 그리고 앞으로 나아갈 방향을 제안합니다.

반응형