개요: src layout?
django 모범 사례에서는 django app의 생성 기준을 하나의 개념 집합 단위로 생성해야 된다고 명시하고 있습니다. 하지만 저는 이렇게 app을 구성하게 될 경우 네이밍을 통해서는 어떤 것이 djjango app에 해당하는 디렉터리인지 구분이 안 가는 상황을 종종 겪곤 합니다. 그러하여 최근엔 django app을 구성할 때 단일 app을 만들고 그 안에 적절한 개념을 생성해서 구분하는 편입니다.
여기서 "단일 app"이라는 말 그대로 django app을 하나만 생성하는 것을 뜻합니다. 이렇게 단일 app을 통한 구성 방식으로 작성하던 도중 뭔가 더 발전시킬 수 있는 방법이 있지 않을까 싶어 프로젝트 구성에 관한 자료를 찾아보던 중 src layout이라는 방법이 있다는 것을 알게 됐습니다.
src layout에 반대되는 구성을 flat layout이라고 부르나 봅니다. Django Project를 초기에 접했을 땐 flat layout 방식에 따라서 구성하곤 했습니다. Github Reposiotry를 바로 Clone 하여 빨리빨리 실행 가능하도록 만들기 편했기 때문이었습니다.
조금 더 시간이 지나 '프로젝트 패키징'이라는 개념을 접하며 이를 Django Project에 녹여보기 전에 시도한 src layout 형태를 연습해 봤습니다.
즉, 이 포스팅은 "저는 src layout 을 djangot에 이렇게 녹여봤습니다" 하는 글입니다.
왜 굳이 src layout을?
src layout으로 django 프로젝트를 구성하기 전에 flat layout 방식의 구성과 비교해 볼 필요가 있습니다.
앞서 언급했듯 flat layout으로 프로젝트를 구성하면 Github Repository에서 바로 Clone 하여 실행하기 때문에 빨리 실행할 수 있었던 것을 장점이라 언급했습니다.
하지만 Django 프로젝트를 구성하는 다른 예시들을 조사하기 위해 Github의 Open Source들을 탐방하다 보면 "이게 뭐 하는 파일이지? 처음 보는데?"라는 생각이 드는 파일들을 보게 됩니다. 이런 파일들을 보고 있으면 프로젝트를 이루는 구성에는 특정 FrameWork에 관련된 내용만 들어가지 않는구나를 뜻한다는 걸 꺠닫곤 합니다.
제 경우엔 Django 프로젝트에 Dockerzing을 적용하기 위해 docker-compose.yml, Dockerfile을 추가할뿐더러 CI/CD를 위해 github action까지 추가하곤 합니다. 이에 더해 Makefile을 추가해 자주 사용하는 Command Set을 등록하기도 하며 프로젝트 스케일에 따라 jenkins와 각종 thrid party와 연결하기 위한 설정들이 추가되면 더 복잡합니다.
물론 구성하기 나름입니다만.. 이렇게 Project에 파일을 하나둘씩 추가하다 보면 Project 구조를 파악하는데 드는 시간이 증가하게 됩니다.
하여 src layout을 통해 source를 구분해 보는 것도 좋은 방법이 될 것이라 생각이 듭니다.
src layout과 Django 프로젝트 구성하기
Python Document에서 src layout 구성을 다음과 같이 표시하고 있습니다.
.
├── README.md
├── noxfile.py
├── pyproject.toml
├── setup.py
├── src/
│ └── awesome_package/
│ ├── __init__.py
│ └── module.py
└── tools/
├── generate_awesomeness.py
└── decrease_world_suck.py
src 디렉터리를 만들고 패키징 할 대상을 이 안에 넣어두는 구조인 듯 싶습니다. 즉 프로젝트 패키징을 src 디렉터리 안 쪽에 있는 코드로 하겠다는 의미로 해석했습니다.
이에 기반하여 Django 프로젝트를 만들 때 구조를 다음과 같은 모습으로 구성해봅시다.
# 1. Project Root 디렉토리에 src 디렉토리 생성
# 2. django-admin startproject config 로 django project 생성
# 3. python manage.py startapp application으로 django app 생성
.
├── requirements.txt
├── src
│ ├── __init__.py
│ ├── application (django app)
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── urls.py
│ │ └── views
│ ├── config (django settings)
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── manage.py
"뭐야 이거 src 디렉터리를 생성하고 django project를 그 안으로 밀어 넣은 것뿐이잖아?"라고 생각하셨다면 그게 맞습니다.
여기서 모든 게 완벽히 끝났으면 좋겠지만 아직 신경 쓸게 남았습니다.
테스트 코드는 어디에?
src layout으로 Django 프로젝트를 구성하는 데 있어서 삽질 시간이 제일 큰 부분이었습니다. 바로 test 코드를 어디에 위치시킬 것인지를 결정하는 단계였습니다.
사실 src layout으로 django project를 구성해 보자는 생각의 발상지는 "파이썬으로 살펴보는 아키텍처 패턴"이라는 책을 읽고 나서입니다. 이 책에서는 test를 src 외부에 구성함으로써 각 구성이 위치해야 될 곳을 명확히 합니다.(참고링크)
이이 따라 test 코드가 들어갈 tests라는 디렉터리를 src layout 밖에다가 생성했습니다
├── src
├── tests # test코드가 위치할 디렉터리
└── venv
여기서 한 가지 짚고 넘어가 봅시다. 위처럼 test 코드를 src layout을 밖에다가 위치시켜 놓는 건 어떻게 보면 Django 프로젝트의 test 코드를 Django Project와 상관없는 곳에 떨궈 놓은 것처럼 보입니다. 이런 상황에서는 Django 설정을 불러들이는 코드를 통해 Django와 연계된 기능을 이용하게 됩니다.
import os
from django.core.files import File
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
import django
django.setup()
하나 위 코드를 매번 테스트 코드를 작성할 때마다 복사 붙여 넣기 할 수는 없는 노릇입니다.
어떻게 하면 tests 디렉터리에서 Django에서 사용하는 model과 view 기타 다른 코드를 테스트할 수 있을까요?
SetUp01, Mark Sources Root
src 디렉터리를 Source Root로 설정합니다. 기존에 flat layout 방식으로 구성했을 땐 Project Source Root를 Root 디렉터리로 설정하면 문제가 없었습니다만 src layout에서는 이 Source들이 src 디렉터리로 이동했기 때문에 Source Root를 변경해줘야 합니다.
저는 Pycharm을 사용하기 때문에 다음과 Source Root를 src 디렉터리로 설정했습니다.
SetUp02, test는 pytest-django를..
제가 지금까지의 구성을 하는 데 사용된 test 모듈은 pytest-django입니다. pytest-django에는 document에서 Project를 src layout에 구성으로 만들 때 pytest.ini에 pythonpath를 설정하라고 가이드해 줍니다.
아래는 제 경우에 작성한 pytest.ini 파일입니다.
# pytest.ini
[pytest]
addopts = -v --reuse-db --no-migrations
django_debug_mode = true
DJANGO_SETTINGS_MODULE = config.settings.local
pythonpath = src tests
마치며..
이렇게 src layout으로 구성해 만든 Project의 최종적인 형태는 다음과 같습니다.
╰─$ tree -L 2
.
├── Makefile
├── README.md
├── docker-compose.yml
├── pytest.ini
├── requirements.txt
├── src
│ ├── __init__.py
│ ├── __pycache__
│ ├── application
│ ├── config
│ └── manage.py
├── tests
│ ├── __init__.py
│ ├── __pycache__
│ ├── conftest.py
추가적으로 docker-compose.yml과 Dockerfile 그리고 Makefile을 추가했음에도 깔끔한 형태로 구분점이 명확히 생겼습니다.
지금까지 설명된 내용의 소스 코드는 여기서 참고할 수 있습니다.
'Frame Work > Django' 카테고리의 다른 글
Django와 MySQL 연결 문제 Exception 탐구 (0) | 2023.06.06 |
---|---|
[Django] show_urls 흉내내기 (0) | 2023.04.09 |
[Django] auth_group 다루기 (0) | 2022.12.18 |
uWSGI Socket + Nginx + Docker (0) | 2022.11.10 |
uWSGI를 알아보자 (0) | 2022.11.05 |