현재 프로젝트가 곧 배포를 준비해야하는 단계에 진입할 것 같아 개발용, 배포용 환경설정의 분리가 필요할 것이라 판단되어 분리를 한 뒤 문서를 작성해봅니다.
0. 왜 사용하나?
사실 우리 프로젝트의 규모에서는 안 써도 딱히 불편함을 없다. 왜냐하면 개발용과 배포용 2가지밖에 없기 때문이다.
즉, settings.py에서 단순하게 DEBUG = True, False를 이용해 간단하게 if문으로 개발, 배포 환경을 분리하는 것이 가능하다.
하지만 그러면 settings.py가 너무 길어질 수 있고(이전 프로젝트가 그랬다.) 많은 if, else에 의해 가독성이 떨어지는 settings.py는 유지보수가 힘들어진다.
1. 어떤 방식으로 분리할 것인가?
기본적인 구조는 아래와 같다.
PnuNoti/
├──settings/
├── __init__.py
├── base.py
├── local.py
├── staging.py
├── test.py
├── production.py
- base.py: 기초가 되는 공통 부분 (프로젝트의 모든 인스턴스에 적용되는 셋팅)
- local.py: 로컬환경에서 실행하는 개발 환경 DEBUG mode, log level, django-debug-toolbar와 같은 개발자용 툴 등이 있다.
- staging.py: 운영 환경으로 코드가 이동되기 전에 관리자 및 고객들의 확인을 위한 서버. 즉 베타테스트 서버
- test.py: test-runners, 인메모리 DB정의, 로그 셋팅을 포함한 테스트 코드 실행 설정
- prod.py: 배포,운영에 사용하는 실제 환경
이번 프로젝트가 큰 프로젝트는 아니기에 staging과 test환경은 필요없다고 판단되어 base, local, prod 이 세 개의 환경만 만들 것이다.
구조는 생각보다 매우 간단하다. 대신 추가적인 설정을 해줘야 한다.
2. 실제 구현해보기
먼저 기존에 사용하던 settings.py를 base.py로 바꿔준다. 그리고 BASE_DIR을 다음과 같이 수정해준다.
#before
BASE_DIR = Path(__file__).resolve().parent.parent
#after
BASE_DIR = Path(__file__).resolve().parent.parent.parent
이유는 settings.py는 ./pnuNoti 에 있지만 바뀌고 난 뒤에는 base.py가 ./pnuNoti/settings/에 있기 때문이다.
그리고 환경에 따라 달라질 수 있는 DEBUG, ALLOWED_HOST, DATABASES는 local.py, prod.py로 옮길 것이다.
SECRET_KEY의 경우에는 지금과 같은 작은 프로젝트에서 구분할 필요가 없어보인다.
더 많은 설정들이 분리될 수 있지만 이는 상황에 따라 달라질 듯 하다.
이 때, 사실 INSTALLED_APPS의 경우도 개발, 배포 단계에서 달라질 수는 있습니다. 그럴 때는 INSTALLED_APPS를 따로 만드는 방법이 아닌 base.py의 INSTALLED_APPS를 가져와 아래와 같이 추가해주면 됩니다.
# /settings/local.py
from .base import *
...
INSTALLED_APPS += ['debug_toolbar',]
3. 사용하기
이제부터 단순하게 python manage.py runserver를 사용하면 settings.py가 인식되지 않아 오류가 발생한다.
그렇기에 다음과 같은 명령어를 상황에 맞게 사용해줘야한다.
python manage.py makemigrations --settings=pnuNoti.settings.local
python manage.py migrate --settings=pnuNoti.settings.local
python manage.py runserver --settings=pnuNoti.settings.local
물론 이렇게 사용하면 기존에 비해서 사용하기에 명령어수가 늘어나 피곤해진다. (개발자는 귀찮은게 싫어요)
그렇기에 환경변수를 이용해 해결하는 방법이 있다. 개발 환경의 경우는 배포를 건드리는 일이 없으므로 local의 셋팅으로 설정하면 된다.
(배포는 docker를 이용하니 docker에서 설정하면 된다.)
환경변수에 DJANGO_SETTINGS_MODULE=pnuNoti.settings.local를 추가해주면 된다.
이때 꼭 가상환경의 환경변수에 추가해주는 것을 추천합니다.
만약 pc전체의 환경변수에 등록하면 DJANGO_SETTINGS_MODULE를 사용하는 모든 장고 프로젝트 명령어들이 저기로 들어가 여러 프로젝트를 관리하기 어려워 질 수 있다.
만약 파이참에서 사용하다면 Run/Debug configurations에서 다음과 같이 설정한 후 실행하면 알아서 동작한다. (runserver만..)
추가
만약 가상환경을 사용하는 중이라면 다음과 같이 환경변수를 관리하는 것이 가능하다.
conda activate [가상환경 이름]
cd $CONDA_PREFIX
mkdir -p ./etc/conda/activate.d
mkdir -p ./etc/conda/deactivate.d
touch ./etc/conda/activate.d/env_vars.sh
touch ./etc/conda/deactivate.d/env_vars.sh
- $CONDA_PREFIX: 실행한 가상환경의 설정 디렉토리를 알려준다. ex) anaconda3/envs/pnu_noti
- ./etc/conda/activate.d: 해당 폴더에 .sh 스크립트들은 가상환경이 실행할 때 자동으로 실행된다.
- ./etc/conda/deactivate.d: 해당 폴더에 .sh 스크립트들은 가상환경이 종료할 때 자동으로 실행된다.
이후 각 env_vars.sh에 다음과 같이 설정해준다.
#!/bin/bash
export DJANGO_SETTINGS_MODULE=pnuNoti.settings.local
#!/bin/bash
unset DJANGO_SETTINGS_MODULE
이렇게하면 가상환경을 켤때만 환경변수 DJANGO_SETTINGS_MODULE에 pnuNoti.settings.local가 등록된다.
만약 virtualenv로 가상환경을 구축한 경우는 링크를 참조하시면 됩니다. (conda랑 거의 비슷하고 동작원리는 같다.)