News Feed

개발자 부담 줄이는 파이썬 앱 패키징 툴 ‘파이앱’ 설정하기

컨텐츠 정보

  • 조회 510

본문

개발자라면 누구나 파이썬 프로그램을 클릭 실행 형식의 독립형 패키지로 재배포하기가 얼마나 어려운 일인지 잘 안다. 여러 써드파티 솔루션이 나와 있지만 모두 단점이 있다. 이 용도로 가장 오래되고 가장 잘 알려진 툴인 파이인스톨러(PyInstaller)는 다루기가 불편하고, 제대로 작동하는 재배포 가능 패키지를 얻기 전까지 상당한 시행착오를 거쳐야 한다. 더 최근 프로젝트인 누이트카(Nuitka)는 파이썬 프로그램을 재배포 가능 바이너리로 컴파일하지만 결과물의 크기가 크고 만드는 데 많은 시간이 걸릴 수 있다.

새로운 프로젝트인 파이앱은 완전히 다른 접근 방식을 취한다. 파이앱은 배포하고자 하는 파이썬 프로젝트에 대한 정보와 함께 소스에서 컴파일하는 러스트 프로그램이다. 결과물인 독립형 바이너리는 실행하면 디렉터리에 프로젝트의 압축을 해제하고 그 자리에서 실행한다. 최종 사용자 시스템에 파이썬이 설치돼 있을 필요도 없다.

파이앱 설정

파이앱은 다른 파이썬 배포 솔루션과 달리 파이인스톨러와 같은 파이썬 라이브러리가 아니다. 또한 프로그램을 가져와 아티팩트를 생성하는 독립형 프로그램도 아니다. 배포하고자 하는 각 파이썬 프로그램에 대한 파이앱 맞춤형 빌드를 만드는 방식을 사용한다.

파이앱을 사용해 파이썬 프로그램을 배포하려면 먼저 다음과 같은 몇 가지 전제 요건을 충족해야 한다.

  • 파이앱의 소스 : 파이앱 소스의 클론을 만들어 다른 프로젝트와 분리된 별도의 디렉터리에 저장한다.
  • 러스트 컴파일러와 기타 필요한 인프라 : 러스트나 러스트 툴에 익숙하지 않더라도 러스트 프로그램을 소스에서 컴파일할 수 있을 정도의 지식은 필요하다. 필자가 작성한 러스트 시작하기 튜토리얼을 보면 도움이 된다.
  • 휠로 패키징된 파이썬 프로그램 : “휠”, 즉 .whl 파일은 파이썬 프로그램과 플랫폼별 구성요소(사전 컴파일된 라이브러리 등)를 패키징하는 데 사용되는 바이너리 형식이다. 다시 패키징하려는 파이썬 프로그램에 대한 휠이 아직 없다면 만들어야 한다. 파이썬 휠 생성을 위한 필자의 비디오 튜토리얼에서는 단계별로 이 과정을 볼 수 있다. 파이파이에 호스팅된 휠을 사용할 수도 있다.

파이앱은 사용자가 컴파일하고자 하는 파이썬 프로젝트가 무엇이고 이를 어떻게 지원할지 파악하기 위해 빌드 프로세스 중에 환경 변수를 사용한다. 가장 일반적으로 사용되는 변수는 다음과 같다.

  • PYAPP_PROJECT_NAME : 번들링할 파이썬 프로젝트의 이름을 정의하는 데 사용된다. pyproject.toml을 사용해서 프로젝트를 정의한 경우 이 값은 project.name 속성과 일치해야 한다. 파이파이 상의 프로젝트 이름일 수도 있는데, 그렇지 않은 경우 사용할 .whl 파일의 경로를 지정해야 한다.
  • PYAPP_PROJECT_VERSION : 필요한 경우 프로젝트의 특정 버전을 구성하는 데 사용된다.
  • PYAPP_PROJECT_PATH : 프로젝트에 사용할 .whl 파일의 경로(상대 또는 절대). 파이파이에서 .whl을 설치하는 경우 생략한다.
  • PYAPP_EXEC_MODULE : 많은 파이썬 패키지는 모듈로 실행될 때 어떤 형태로든 자동으로 실행된다. 이 변수는 어떤 모듈을 사용할지 선언할 수 있게 해준다. 따라서 프로그램이 thisprogram이라는 이름으로 실행된다면 이 변수를 python -m thisprogram으로 설정해야 한다.
  • PYAPP_EXEC_SPEC : 진입점 스크립트가 있는 프로그램의 경우 이 변수에 지정할 수 있다. pyproject.tomlproject.scripts 섹션 구문과 일치한다. 예를 들어 pyprogram.cmd:main은 파이썬 프로그램의 모듈에서 pyprogram.cmd 모듈을 가져온 다음 이 모듈에서 main() 함수를 실행한다.
  • PYAPP_EXEC_SCRIPT : 이 변수는 임의의 파이썬 스크립트에 대한 경로를 제공할 수 있게 해준다. 그러면 해당 스크립트는 바이너리에 임베딩되고 시작 시 실행된다.
  • PYAPP_DISTRIBUTION_EMBED : 일반적으로 파이앱 바이너리를 생성하면 이 바이너리는 처음 실행될 때 인터넷에서 프로그램 실행에 필요한 파이썬 배포판을 다운로드한다. 이 변수를 1로 설정하면 파이앱은 생성된 바이너리에 필요한 파이썬 배포판을 미리 패키징한다. 결과적으로 바이너리의 크기는 커지지만 아무것도 다운로드할 필요가 없으므로 스스로 압축을 해제하고 실행할 수 있다.

그 외에도 많은 옵션이 있지만 대부분의 프로젝트에서는 이 변수로 충분할 것이다.

쉽게 하려면 각 프로젝트에 대한 셸 스크립트를 만들어 이러한 환경 변수를 설정하고 컴파일 프로세스를 실행하면 된다.

파이앱 바이너리 빌드하기

환경 변수를 설정했으면 파이앱 소스의 루트 디렉터리로 가서 러스트 컴파일러를 사용해 다음 명령으로 파이앱을 빌드한다.

cargo build --release 

파이앱에는 많은 종속 항목이 있으므로(이 글을 쓰는 현재 363개) 빌드에는 몇 분 정도 걸릴 수 있다. 러스트가 모든 요소를 확보하고 캐시하면 이후의 컴파일은 훨씬 더 빠르게 진행된다.

참고로 다른 플랫폼을 위한 크로스 컴파일도 가능은 하지만 권장되지 않으며 지원도 되지 않는다.

컴파일이 완료되면 결과 바이너리는 파이앱 프로젝트 디렉터리의 target/release 하위 디렉터리에 pyapp.exe로 저장된다. 결과 파일의 이름은 확장자를 제외하고 자유롭게 변경할 수 있다.

파이앱 바이너리 실행

바이너리를 테스트하려면 콘솔에서 실행하면 된다. 정상적으로 진행될 경우 파이앱이 압축 해제되고 실행을 준비하는 동안 콘솔에 프롬프트가 표시된다. 콘솔에 오류가 표시되면 기록하고 환경 변수를 수정한다. 대부분의 오류는 프로젝트의 진입점이나 시작 스크립트를 제대로 설정하지 않아서 발생한다.

파이앱 바이너리를 처음 실행하면 일반적으로 사용자 프로필의 하위 디렉터리에 압축이 해제된다. 이후 실행할 때는 이미 압축 해제된 사본을 사용하므로 실행 속도가 훨씬 더 빨라진다.

바이너리 압축이 해제되는 위치를 직접 정하려면 환경 변수를 설정해서 프로그램이 실행될 때 압축 해제된 파일을 쓸 위치를 지정하면 된다.

PYAPP_INSTALL_DIR_ = "path/to/directory"

참고로 PYAPP_PROJECT_NAME 변수의 대문자 버전이다. 따라서 conwaylife 프로그램의 경우 PYAPP_INSTALL_DIR_CONWAYLIFE라는 변수 이름을 사용한다. 디렉터리는 전체 경로이거나 상대 경로일 수 있으므로 ./app과 같은 디렉터리를 사용해서 애플리케이션에 현재 작업 디렉터리의 하위 디렉터리 app에 압축을 해제하도록 지정할 수 있다.

또 하나 참고할 점은 이 설정이 영구적이지 않다는 것이다. 즉, 프로그램을 실행할 때 이 환경 변수를 설정하지 않으면 기본값인 user-profile 디렉터리가 사용된다.

파이앱 옵션

배포된 파이앱 실행 파일에는 다음과 같은 편리한 명령이 내장돼 있다.

  • pyapp self remove : 압축 해제된 앱을 압축 해제된 디렉터리에서 제거한다.
  • pyapp self restore : 앱을 제거하고 재설치한다.

PYAPP_INSTALL_DIR_ 변수를 사용해서 프로젝트 위치를 설정한 경우 위의 명령을 실행할 때도 이 변수가 설정돼 있어야 한다는 점에 유의해야 한다. 또한 파이앱으로 패키징된 앱의 실행 파일에는 기본적으로 코드 서명이 되어 있지 않아 마이크로소프트 윈도우의 안티바이러스 프로그램에서 오탐지를 일으킬 수 있다는 점도 알아둬야 한다.
dl-itworldkorea@foundryco.com

관련자료

댓글 0
등록된 댓글이 없습니다.
Member Rank