배포전 개발환경 분할하기

개발 환경을 local, dev, production 으로 분할 해보자

.secrets 폴더에 local, dev, production .json파일을 만들자 config/settings.py를 패키지화 시키자. settings라는 모듈로 만들어서 사용한다. settings 패키지에 ‘base, local, dev, production .py파일을 만들자 init.pybase.py로 옮기고 각각의 설정을 개발환경에 맞에 나누어 보자 Debug옵션은 각 설정마다 다르다 로컬은 True지만 배포의 경우 False` 이기 때문에 각 환경에 다 넣어 준다.

# local.py, dev.py 
Debug = True
# production.py
Degub = False

ALLOWED_HOSTS 도 각 환경에 다 넣어 준다. INSTALLED_APPS도 각 환경마다 따로 설정 할 수 있지만, 지금은 수정하지 않는다. DATABASES도 환경에 따라 다 넣어 준다. 넣어 주기 전에 DATABASES의 내부 값들은 보호되어야 하므로 .secrets폴더의 각 환경에 맞는 설정파일로 빼서 사용하자.

`.secrets/local.json`
{
  "DATABASES": {
    "default": {
      "ENGINE": "django.db.backends.postgresql",
      "HOST": "localhost",
      "NAME": "<DB Name>",
      "USER": "<DB User Name>",
      "PASSWORD": "<DB Passwrod>",
      "PORT": <Port Default:5432>
    }
  }
}
`.secrets/dev,production.json`
{
  "DATABASES": {
    "default": {
      "ENGINE": "django.db.backends.postgresql",
      "HOST": "<AWS Rds Endpoint>",
      "NAME": "<DB Name>",
      "USER": "<DB User Name>",
      "PASSWORD": "<DB Passwrod>",
      "PORT": <Port Default:5432>
    }
  }
}

그리고 local.py를 셋팅 모듈이 되도록 해보자.

manage.pyDjango의 셋팅 모듈은 config.settings가 기본으로 되어 있다. 하지만 우리는 config.settings를 모듈이 아닌 패키지로 만들어 놓았다. 로컬에서는 local postgresql을 사용하고 배포 환경에서는 S3 posrgresql을 사용하게 만들어야 한다. 현재 셸 환경에서 환경 변수를 설정 해보자

export DJANGO_SETTINGS_MODULE=config.settings.local

이렇게 하고 env로 확인해보면 현재 셸의 환경 변수에 등록 되어 있는것을 볼수 있다. 이제 이 환경에서 ./manage.py를 실행하게 되면 DJANGO_SETTING_MODULE이 있기 때문에 기본 모듈인 config.settings를 사용하지 않고 우리가 방금 지정해준 config.settings.local을 사용하여 실행하게 된다. 이후 ./manage.py를 실행하면 SECRET_KEY가 비어 있다고 나온다. 왜냐하면 각 local.py에는 해당 변수가 없기 때문이다. 물론 다른 환경도 마찬가지이다. base.py를 불러 와보자

# local, dev, production.py
from .base import *

그리고 base.py에서 또 오류가 날것인데 이것을 수정 해보자. 오류가 나는 이유는 base.py에서 BASE_DIR의 기준이 달라졌기 때문이다. BASE_DIR을 한단계 더 밖으로 나오게 설정하자.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

이제 각 환경 별로 DATABASES를 설정 해 주어야 한다. 그 전에 base.py에 각 환경별 .secrets/.json파일을 읽어와야 한다.

# base.py
SECRETS_LOCAL = os.path.join(SECRETS_DIR, 'local.json')
SECRETS_DEV = os.path.join(SECRETS_DIR, 'dev.json')
SECRETS_PRODUCTION = os.path.join(SECRETS_DIR, 'production.json')

그리고 가져다 쓰자.

# local.py
secrets = json.loads(open(SECRETS_LOCAL, 'rt').read())
DATABASES = secrets['DATABASES']
# dev.py
secrets = json.loads(open(SECRETS_DEV, 'rt').read())
DATABASES = secrets['DATABASES']
# production.py
secrets = json.loads(open(SECRETS_PRODUCTION, 'rt').read())
DATABASES = secrets['DATABASES']

그런데 생각해보니 local에 postgresql을 만든적이 없다. 만들어 보자.

sudo -u postgres createdb ec2_deploy --owner=<postgresql superuser name>

유저가 없다면 만들자.

sudo -u postgres createuser -P -s <user name>

그리고 셸을 개발 환경별로 셋팅해놓고 마이그레이션을 확인해보자 local은 아무것도 안되어 있을 것이고 dev는 마이그레이션이 되어 있는것이 보인다. local의 경우 방금 db를 생성하고 마이그레이션을 안해 주었기 때문이고 dev는 이미 S3에 마이그레이션을 했었기 때문이다.

그리고 deploy-ec2를 해보자 그러면 또 SECRET_KEY가 없다는 에러가 날 것이다 ㅠㅠ 끄어어 서버의 셸에도 환경 변수를 설정 해줘야 하는데 그런 방법은 없다. 하지만 config/settings/wsgi.py안에 환경 변수를 셋팅하는 부분이 있다. 이것을 사용하여 각 환경에 맞게 환경변수를 할당 시켜보자. 결국 wsgi.py도 환경별로 만들어야 한다는 소리다. 후.. wsgi.py를 패키지로 만들고 각 환경에 맞는 파이썬 소스를 추가 한다.

# 각 환경별로 코드 수정
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local/dev/production")

수정후 .config/uwsgi.ini파일의 module을 각 환경에 맞게 수정 해 주어야 한다. 그리고 deploy.shbash가 실행되기 전 export로 해당 셸에 환경 변수를 설정해 줘야 한다. 이유는 이전에 export로 설정해준 환경 변수(settings.local 등)는 ./manage.py를 실행 할 때만 적용 되는 것이고 deploy.sh를 실행 할때는 적용 되어 있지 않기 때문이다.

# .config/deploy.sh
export DJANGO_SETTINGS_MODULE=config.settings.dev

이후 deploy 하면 잘 되는 것을 볼 수 있다.

Comments