Settings 분리하기

settings.py

settings.py 를 왜 분리해야할까?

보통 프로젝트를 시작하면 한개의 settings.py 파일이 존재한다. 하지만 실무에서는 로컬환경, 배포환경으로 환경설정이 나누어져있다. 로컬환경은 일반적으로 오류를 검출하기 위한 환경을 가지며, 배포환경에서는 로그 기록이나 오류를 숨겨 사용자 편의성을 도모하고 악의적인 해커로부터 보호하는 환경을 설정한다.

config/
├── __init__.py
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── development.py
│   └── production.py
├── urls.py
└── wsgi.py

base.py

settings/base.py 에는 1. 각 종 경로 2. 언어, 타임존 등 공통으로 사용되는 설정들이 저장된다.

공통으로 사용되는 각 종 디렉토리 경로, AUTH_USER_MODEL, INSTALLED_APPS 등이 base.py에 설정하게된다.

"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 2.1.7.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os
import sys
import json

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ROOT_DIR = os.path.dirname(BASE_DIR)
SECRETS_PATH = os.path.join(ROOT_DIR, '.config_secret')
SECRET_BASE_FILE = os.path.join(ROOT_DIR, 'base.json')

# json 파일을 python 객체로 변환
base_secrets = json.loads(open(SECRET_BASE_FILE).read())

# json은 dict 자료형으로 변환되므로 .items() 함수를 이용해 key와 value값을 가져온다.
# 이때 settings 모듈에 동적으로 할당한다.
for key, value in base_secrets.items():
    setattr(sys.modules[__name__], key, value)

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'config.wsgi.application'

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'ko'

TIME_ZONE = 'Asia/Seoul'

USE_I18N = True

USE_L10N = True

USE_TZ = True

development.py vs Production.

Static 파일의 경로, DB 종류, WSGI 설정, allowed host 등 다양하게 설정을 분리할 수 있다.

development.pyp.py 를 구분짓는 가장 핵심은 Debug 값이다.

Debug = True

왜 오류가 났는지 알려주지 않으며 단순히 페이지를 찾을 수 없다는 문구만나온다.

Debug = False

오류가 난 이유를 상세하게 알려준다. 어느 파일, 몇번째 줄에서 오류가 발생했는지 알 수 있다.

$ ./manage.py runserver --settings=config.settings.development # 개발용
$ ./manage.py runserver --settings=config.settings.production # 배포용

development.py

from .base import *

SECRETS_DEV_FILE = os.path.join(SECRETS_PATH, 'development.json')

dev_secrets = json.loads(open(SECRETS_DEV_FILE).read())

DEBUG = True

INSTALLED_APPS += [
    'debug_toolbar',
]

MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.path.join(BASE_DIR, 'db.mysql'),
        'USER': dev_secrets['DATABASES']['USER'],
        'PASSWORD': dev_secrets['DATABASES']['PASSWORD']
    }
}

Manage.py

#!/usr/bin/env python
import os
import sys

if __name__ == '__main__':
  # setdefault를 development로 설정해준다.  
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)

wsgi

uswgi명령을 통해서 직접 웹어플리케이션 서버를 실행할 때 사용할 설정 파일을 실행 환경별로 분리할 수 있다.

config/
├── __init__.py
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── development.py
│   └── production.py
├── wsgi
│   ├── __init__.py
│   ├── development.py
│   └── production.py
├── urls.py
└── wsgi.py

Development.py

"""
WSGI config for config project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')

application = get_wsgi_application()

production.py

"""
WSGI config for config project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production')

application = get_wsgi_application()

requirements.txt

어떤 패키지는 운영 시에는 사용되지 않지만 개발의 편의를 위해서 필요한 경우가 있다. 이러한 경우에 requirements.txt 파일을 분리해서 사용하기도 한다.

├── app
│   ├── config
│   │   ├── __init__.py
│   │   ├── settings
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   ├── development.py
│   │   │   └── production.py
│   │   ├── urls.py
│   │   └── wsgi
│   │       ├── __init__.py
│   │       ├── development.py
│   │       └── production.py
│   └── manage.py
└── requirements
    ├── base.txt
    ├── development.txt
    └── production.txt

base.txt

Django==2.1.7
[...]

development.txt

-r base.txt
django-debug-toolbar==2.0
[...]

참고 페이지

Last updated