무슨 프로그램 언어를 사용하여 어떤 프로젝트를 진행하든지 간에, 프로그램의 이식성은 아주 중요한 이슈입니다.
기껏 개발용 컴퓨터에서 동작이 잘 되도록 잘 만들었는데, 정작 실제 서비스를 위한 Production Server에 옮기고 실행했을 때 여태껏 본 적이 없는 오류를 뿜어내며 구동이 되지 않는다면 참 기가 막히고 답답할 것입니다. 이렇게 되면 개발 처음부터 완성까지 어떤 의존성 패키지를 설치하고 어떻게 세팅했는지 기억을 더듬어가며 똑같은 과정을 한 번 더 반복해야만 합니다. (물론 그런다고 항상 잘 된다는 보장은 없습니다.^^ - 경험에서 우러나온 언급[...])
파이썬에서는 이런 귀찮은 문제를 깔끔하게 해결할 수 있도록 Sandbox개발 환경을 사용할 수 있습니다. 프로젝트를 시작하기 전에 Sandbox를 만들어 놓고 그 안에서 지지고 볶고 하다가, 완성이 되면 Sandbox에 설치했던 의존성 패키지들의 목록만 한번에 쭉 뽑아내서 파일 하나로 정리해 Production Server로 가져가거나 배포하는 것입니다.
Sandbox를 사용해 개발하면 이전 설치(Migration)가 용이해진다는 편리함 외에, 전체 시스템에 영향을 주지 않고 필요한 패키지를 마음껏 설치했다 지웠다 할 수 있다는 편리함도 누릴 수 있습니다.
이러한 특성은 서로 다른 버전의 모듈을 사용하는 두 개 이상의 프로젝트를 동시에 진행하고 있는 상황에서 요긴하게 활용할 수 있습니다. 서로 다른 Sandbox 내에서 서로 다른 버전의 모듈을 설치해서 동시에 개발을 진행할 수 있기 때문입니다.
VirtualEnv 설치하기
Ubuntu 환경이라면 Repository에 이미 관련 패키지가 등록되어 있으므로 apt-get으로 간단히 설치할 수 있습니다.
$ sudo apt-get install python-virtualenv
Sandbox 생성하기
샌드박스를 사용할 프로젝트 디렉토리로 이동하여 virtualenv명령을 사용하여 Sandbox를 생성할 수 있습니다. 다음 명령을 실행하면 venv라는 이름의 Sandbox가 생성됩니다.
venv라는 이름은 임의로 지정한 것이며, 필요에 따라 다른 이름을 사용하거나 같은 프로젝트에 여러 개의 Sandbox를 생성하여 번갈아가며 사용하는 것도 가능합니다.
--python 옵션으로 Sandbox내에서 사용할 python 바이너리의 원본을 지정할 수 있습니다. 옵션을 주지 않으면 기본으로 현재 시스템에 전역으로 설치된 Python을 사용합니다.
$ virtualenv venv --python=$(which python)
이렇게 하면 현재 위치에 venv라는 이름의 디렉토리가 생성됩니다. 이 디렉토리가 생성되었다고 해서 바로 Sandbox모드로 진입하는 것은 아닙니다. 사실상 virtualenv 명령이 하는 일은 이 디렉토리를 만들어 주는 것 뿐입니다. 이제 이 디렉토리를 활용해서 필요할 때 수동으로 Sandbox 모드로 진입해야 합니다.
Sandbox 활성화하기
VirtualEnv의 동작 원리는 PyEnv의 동작 원리와 같습니다. Shell의 Path를 변경해서 Python이 설치된 Home Directory가 Sandbox에 설치된 가상 Home Directory를 가리키도록 하는 것입니다.
물론, 이 작업을 수동으로 해야 되는 것은 아니며, Sandbox를 만들 때 같이 생성된 Script를 실행해서 간단히 Sandbox를 활성화할 수 있습니다.
$ . venv/bin/activate
이 명령을 실행하면 앞에 다음과 같이 Shell 앞에 현재 사용중인 Sandbox의 이름이 표시됩니다.
Sandbox내에 패키지 설치하기
Sandbox가 활성화된 상태에서 pip명령을 활용해 패키지를 설치하면 전체 시스템에 설치되는 대신 Sandbox내에 패키지가 설치됩니다.
(venv)$ pip install {설치할 패키지 이름}
Sandbox에 설치한 패키지 목록 추출하고 복원하기
다음 명령을 통해 현재 Sandbox내에 설치된 패키지 목록을 '확인'할 수 있습니다.
(Sandbox 밖에서 이 명령을 실행하면 시스템 전체적으로 설치된 패키지 목록이 출력됩니다.)
(venv)$ pip freeze
이를 파일로 Output Redirection하면 패키지 목록을 담은 파일을 생성할 수 있습니다. 이 파일 이름에 특별한 규칙은 없지만, 통상적으로 'requirements.txt'를 가장 많이 사용하는 것 같습니다.
(venv)$ pip freeze > requirements.txt
이렇게 생성한 requirements.txt파일을 이용해 다른 시스템(혹은 Sandbox) 내에 의존성 패키지를 손쉽게 설치할 수 있습니다. 다음은 requirements.txt파일을 읽어서 그곳에 기재된 의존성 패키지를 모두 설치하는 명령입니다.
$ pip install -r requirements.txt
Sandbox 해제하기
Sandbox 내에서 다음 명령을 입력하여 Sandbox를 벗어날 수 있습니다.
(venv)$ deactivate
위 명령을 실행하면 Shell앞에 붙었던 Sandbox 이름이 사라지며 Sandbox에서 벗어납니다.
deactivate 명령은 단순히 Sandbox에 관련된 환경변수를 모두 삭제하여 원래 Shell 환경으로 만들어 줄 뿐입니다. 즉, Sandbox를 활성화했다가 해제할 때 새로운 프로그램이나 Shell이 실행되고 종료되는 것이 아닙니다.
(VirtualEnv를 처음 쓸 때 무심코 exit를 쳤다가 Shell이 닫혀버리는 바람에 적잖게 당황했던 기억이 스치는군요..;;;)
버전관리와 VirtualEnv, Migration 절차
프로젝트에 GIT과 같은 버전관리 시스템을 사용한다면, VirtualEnv를 사용함에 있어 한 가지 더 고려해 보아야 할 사항이 생깁니다.
- 바로, 어떤 디렉토리/파일을 Tracking할지 여부를 결정해야 합니다.
Sandbox를 생성하면 해당 이름의 디렉토리가 프로젝트 디렉토리에 생성됩니다. 이 디렉토리가 바로 Sandbox의 실체이며, Sandbox에서 설치한 의존성 패키지는 모두 이 디렉토리에 설치가 됩니다.
그렇다면, 이 디렉토리는 버전관리에서 Tracking을 해야 할까요, 아니면 무시해도 될까요?
이 질문은, 완성된 프로젝트를 배포/이전할 때 Sandbox를 들고 다녀야 하는지 여부를 묻는 질문과 같습니다.
정답만 간략히 말하면, No입니다.
완성한 프로젝트를 배포하거나 다른 시스템으로 이전할 때 필요한 파일은 pip freeze를 통해 추출한 requirements.txt 파일 뿐이며, Sandbox(venv) 디렉토리는 필요하지 않습니다.
이는 Node.js에서 npm을 통해 설치한 패키지들이 위치하는 디렉토리인 node_modules 디렉토리를 들고 다니지 않고 오직 package.json만 포함하여 배포하는 것과 같은 이치입니다.
게다가, 생성한 Sandbox는 현재 시스템에서만 유효하며, 다른 시스템으로 이전한 경우 사용할 수 없으므로 새로 만들어 주어야 합니다. 시스템에 따라서 환경 변수가 제각각 모두 다르기 때문입니다.
만약 다른 시스템에서 생성한 Sandbox를 활성화하고 pip관련 명령을 실행하면 다음과 같이 원인을 알 수 없는(?)에러를 뿜어댈 것입니다.
Could not find platform independent libraries <prefix> Could not find platform dependent libraries <exec_prefix> Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>] Fatal Python error: Py_Initialize: Unable to get the locale encoding ImportError: No module named 'encodings' Aborted (core dumped)
버전관리 시스템으로 GIT을 사용한다면, 당장 .gitignore에 사용하는 Sandbox이름을 추가해서 더 이상 Tracking하지 않도록 설정하도록 합니다.ㅎㅎ
Migration 절차
위에서 언급한 내용을 통해 완성한 프로젝트를 다른 시스템으로 옮겨왔을 때 어떠한 절차를 밟아야 하는지 정리해 볼 수 있습니다.
1. Sandbox를 생성합니다.
$ virtualenv venv
2. Sandbox를 활성화합니다.
$ . venv/bin/activate
3. requirements.txt파일을 통해 의존성 패키지를 설치합니다.
(venv)$ pip install -r requirements.txt
- [Django Tutorial] 9. Production - uWSGI를 통해 Nginx 웹 서버와 연동하기 (11361) *1
- [Django Tutorial] 8. Production - setting.py설정, Static파일 모으기 (5488)
- [Django Tutorial] 7. 백엔드 콘솔에 Custom Command 추가하기 (4170)
- [Django Tutorial] 6. Database 연동하기 - Model설계, Migration (30170)
- [Django Tutorial] 5. Static 파일 사용하고 관리하기 (9277)
- [Django Tutorial] 4. URL Config, Template 및 View의 동작에 대한 이해 (9219)
- [Django Tutorial] 3. 프로젝트 및 App 생성, settings.py수정(DB연동, Migration), Runserver (12322)
- [Django Tutorial] 2. 개발 환경 세팅하기 - pyenv 및 virtualenv 활용 (6614)
- [Django Tutorial] 1. 파이썬 기반 웹 프레임워크 Django에 대한 소개 (10949) *2
- pyenv를 이용하여 여러 버전의 Python 동시에 사용하기 (14712) *3