Poetry 를 이용한 쉬운 Python 프로젝트 환경 관리
F-Lab : 상위 1% 개발자들의 멘토링
안녕하세요. F-Lab 'Python Backend' 과정 멘토 Jacob 입니다. 저는 센드버드 출신의 엔지니어링 조직 문화와 생산성에 관심이 많은 개발자입니다. 오늘은 파이썬 환경 관리의 어려움에 대해 알아보고 그 해결책으로 poetry 를 소개하려고 합니다.
개요
Python 은 pip 라는 패키지 매니저와 pypi 라는 중앙화 된 저장소를 제공합니다. pip install / uninstall 명령어를 이용해서 간단하게 원하는 패키지를 다운로드 받아서 설치할 수 있습니다. 하지만 pip 를 실무에서 사용하다 보면 이 접근법이 복잡한 의존성 관리에 적합하지 못하다는것을 느낄 수 있습니다.
패키지 관리의 어려움
일반적으로 제안되는 패키지 관리 방식에 따라서 로컬 환경에서 pip install 을 이용해 'requests’ 패키지를 설치하고 pip freeze 명령어를 이용해서 로컬 환경에 설치한 패키지들을 출력하면 아래와 같은 내용을 확인할 수 있습니다.
<code class="language-plaintext">certifi==2024.2.2 charset-normalizer==3.3.2 idna==3.7 mypy==1.8.0 mypy-extensions==1.0.0 requests==2.31.0 tomli==2.0.1 typing_extensions==4.9.0 urllib3==2.2.1
필자가 설치한 것은 'requests’ 패키지 하나뿐인데 아홉개의 패키지가 설치되어 있는 것을 확인할 수 있습니다. 'requests’ 패키지가 의존성을 가지는 다른 패키지들이 설치되었기 때문입니다. pip 는 현재 설치된 패키지들 중 어떤 것이 사용자가 설치한 것이고 어떤 것이 의존성 패키지에 해당하는지 알지 못하기 때문에 pip freeze 를 이용해서 프로젝트 환경 관리를 하게 되면 필연적으로 requirements.txt 파일을 관리하는 여러가지 내부 규칙들을 만들어내게 됩니다.
그렇다면, pip uninstall 을 이용해서 'requests’ 패키지를 제거한 후에 pip freeze 명령어를 실행시키면 어떤 결과가 나올까요? 아래와 같이 의존성 패키지들이 삭제되지 않은 것을 확인할 수 있습니다.
<code class="language-plaintext">certifi==2024.2.2 charset-normalizer==3.3.2 idna==3.7 mypy==1.8.0 mypy-extensions==1.0.0 tomli==2.0.1 typing_extensions==4.9.0 urllib3==2.2.1
이것은 위에서 이미 배운것처럼 pip 는 현재 설치된 패키지들 중 어떤 것이 사용자가 설치한 것이고 어떤 것이 의존성 패키지에 해당하는지 알지 못하기 때문에 일어나는 일입니다.
다른 패키지 관리 도구
위와 같이 pip 에서 제공되는 기능들만 가지고 프로젝트의 환경 관리를 하기에는 무리가 있을 것 같습니다. 이런 문제점을 해결하기 위해서 pip-tools 와 같은 도구들이 만들어졌습니다. 가령 위에서 언급한 어떤 것이 사용자가 설치한 것이고 어떤 것이 의존성 패키지에 해당하는지 알지 못하는 문제를 해결하기 위해서는 pip에서 직접 패키지를 설치한 후 pip freeze 로 리스트를 출력하는 것이 아니라 pip-compile 이라는 도구를 이용해서 설치하고자 하는 패키지의 리스트를 기반으로 설치해야 하는 패키지들과 그 버전에 해당하는 파일을 만들어낼 수 있습니다.
하지만 이러한 도구를 사용하는 것은 로컬 환경과 통합되어있지 않기 때문에 로컬 환경에서 새 패키지를 도입하거나 패키지 버전을 업그레이드할때 수고가 많이 들게 됩니다.
poetry
poetry 는 pip 가 가지고 있는 여러 문제점들을 해결하고 더 나은 프로젝트 관리 경험을 제공하기 위해서 만들어진 프로젝트 관리 도구입니다. 초기에는 Python 의 의존성 관리 및 패키지 버전 관리를 보다 효율적으로 처리하기 위한 목적으로 시작되었고 이후에 자체적인 가상 환경과 프로젝트 패키징, 그리고 플러그인 시스템과 같은 프로젝트 관리를 쉽게 하기 위한 기능들이 포함되었습니다.
poetry 는 ‘~.toml’ 형식의 파일을 사용하여 프로젝트 Python 버전과 의존성, 빌드 정보와 버전과 같은 메타데이터를 관리합니다. 이 파일은 사용자가 직접 수정할수도 있지만 메타데이터를 제외하면 많은 경우에 자동으로 관리됩니다.
poetry 가 pip 와 비교해서 개선된 점은 다음과 같습니다.
- Python 버전 관리 : 의존성 패키지들은 각각 다른 Python 버전에서 동작할 수 있습니다. poetry 는 Python 버전을 명시적으로 관리함으로써 의존성 패키지들이 의도한 Python 버전에서 동작하는것을 보장합니다.
- 결정론적 패키지 관리 : 같은 프로젝트 파일을 이용했을때 항상 같은 패키지들이 설치되는 것을 보장합니다. 이는 프로젝트의 환경을 쉽게 재현하고 공유할 수 있도록 도와줍니다.
- 버전 충돌 방지 : poetry 는 프로젝트 내에서 의존성 패키지를 추가하거나 업그레이드 할때 의존성 충돌이 일어나지 않도록 보장합니다.
- 세분화된 의존성 관리 : poetry 는 의존성 패키지들을 여러 그룹으로 나누어서 관리할 수 있도록 해 줍니다. 가령 pytest 나 pylint 와 같은 패키지들은 테스트를 실행하고 코드가 문법 규칙을 잘 준수하는지 확인하는 상황에서만 필요합니다. 이런 패키지들을 별도의 그룹으로 나누어서 관리하면 프로덕션 환경에 꼭 필요한 패키지만 포함시킬 수 있습니다.
더해서 poetry 는 프로젝트에서 사용 가능한 가상 환경을 제공합니다. 따라서 로컬 환경에서 개발을 할 때 virtualenv와 같은 별도의 도구를 사용하지 않고도 로컬 Python 환경에 여러 프로젝트의 의존성 패키지가 설치되면서 생기는 문제들을 예방할 수 있습니다. 또 poetry-dotenv-plugin 과 같은 플러그인들을 이용해 환경 변수 관리와 같은 일도 쉽게 할 수 있고 poetry publish 명령어로 pypi와 같은 패키지 저장소에 프로젝트를 업로드할수도 있습니다.
poetry 의 또 다른 장점은 도입이 아주 쉽다는 것입니다. pipx 와 같은 패키지 관리 도구 또는 install.python-poetry.org 에서 배포되는 설치 스크립트를 이용하면 로컬 환경에 poetry를 설치할수 있습니다. 설치한 후에는 poetry init 으로 프로젝트를 시작하고 poetry add 와 poetry remove 명령어를 이용해서 의존성 패키지들을 관리할 수 있습니다. poetry 가 생성한 파일들을 공유함으로써 여러 개발자들이 일관된 환경에서 개발을 할 수 있습니다.
마무리
Python 생태계에서 프로젝트 환경 관리는 너무 잘 알려진 문제여서 그것을 풍자하는 만화도 있을 정도입니다. (위에 '개요'에 사용 된 이미지) 필자도 로컬 환경에 만화에서 그려진 것 처럼 엉망징창이 되어서 하루종일 일을 하지 못하고 문제 해결만 한 경험이 있는데 poetry 도입 이후에는 그러한 일이 전혀 없었습니다. 만화와 같은 상황에 처해서 곤란을 겪기보다는 poetry 를 도입해보시면 어떨까요?
이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.