-
일반적인 Django 서비스는 단일 앱을 통해 개발해야합니다.기술/Django 2022. 12. 11. 20:22
Django의 프로젝트 구조
Django를 시작하면 아래와 같은 구조로 사용하게 됩니다.
- project - namespace1 - models.py - migrations - urls.py - namespace2 - ...
네임스페이스를 하나 정의하고 해당 네임스페이스에서 사용되는 스키마, 뷰, URL를 정의하고 노출합니다. 이를 Django에서는 앱이라고 부르고 있습니다.
문제점
저는 앱을 보통 도메인을 나눠서 관리하면 좋을 것 같다고 생각하게 되면 나눕니다. 유저를 다루는 앱이 있고, 새로 물류와 관련된 기능을 작성해야 한다면 물류라는 앱을 만들고, 계약과 관련한 기능을 나누어 앱을 만드는 것과 같이 어느 정도 큰 단위의 도메인을 다루게 된다면 나누게 되었던 것 같습니다.
하지만 이렇게 앱을 나누면 몇가지 문제가 발생하였습니다.
- 물류, 계약간의 외래 키, M2M 관계가 생기면 의존성이 양방향으로 생깁니다.
- 물류, 계약을 모두 포함해야하는 로직을 어디에 두어야 할지 고민하게 됩니다.
의존성이 양방향으로 생기는게 무슨 문제라고 생각이 들까요? 이는 앱이라는 역할에 맞지않는 구조이기 때문에 문제가 됩니다. 양방향 의존성이 생기는 기능들은 앱에 의해 나누어지면 안 되는 기능들입니다.
앱의 역할
Django 에서 App 은 다음과 같은 역할을 하고 있습니다.
- 재사용 가능한 구성 요소를 논리적으로 분리하고 키고 끄기 쉬운 방법을 제공합니다.
- 충돌을 해결하는 상황을 더 적게 만들 수 있습니다.
- 글로벌 마이그레이션을 관리하는 경우 선형을 유지하기 위해 매번 개발자의 노력이 필요하지만, 각 앱에서 마이그레이션을 관리하는 경우 앱의 개발자끼리만 충돌을 관리하면 됩니다.
- 앱 내 모든 요소들에 대한 충돌을 방지할 수 있습니다.
- 즉, 여러 앱에 동일한 이름을 가진 것들이 존재할 수 있습니다.
다시 문제점으로
앱의 핵심은 재사용 가능 구성 요소를 논리적으로 분리하고 키고 끄기 쉬운 방법을 제공하기 위한 기능이라는 것입니다. 이는 앱이 독립적이고 느슨하게 결합되어 있는 한 작동합니다. 하지만 프로젝트가 성장함에 따라 앱 간에 얽히는 경향이 있습니다. 논리적으로 보이는 앱 분할로 시작하지만 요구사항이 변경되고 프로젝트 내 유틸리티가 개발됨에 따라 모든 방향에서 종속성이 생깁니다. 앱 1 은 앱 2의 모델에 의존하고, 앱 2는 앱 1의 유틸리티에 의존합니다. 외래 키와 M2M 은 양방향으로 의존성이 생깁니다.
복잡하게 얽힌 의존성은 앱의 역할인 재사용성과 키고 끄는 기능을 무력화합니다. 의존성으로 인해 하나의 앱을 재사용할 수 없습니다. 의존성을 가진 모든 앱을 한번에 배포해야 합니다. 또한 키고 끄는 기능 또한 의존성으로 인해 모든 관련 앱을 한 번에 끄고 켜야 합니다.
이 시점에서 리팩토링을 하기는 매우 어렵습니다. Django는 모델 간 이동을 자동으로 지원하지 않습니다. 수동으로 코드를 옮겨야 합니다. 사용자 지정 마이그레이션이 필요하고 이는 사소한 작업이 아닙니다. Admin을 사용하는 경우 URL 도 변경되고 UI의 위치도 변경됩니다.
제안
이 문제를 해결하기 위해 저는 단일 앱에서 개발하는 것을 권장할 것 같습니다. 하나의 서비스를 개발하면 거의 대부분의 기능들이 서로 의존성이 생길 것입니다. 이는 결국 하나의 앱에서 개발해야한다는 것을 의미합니다. 하나의 앱에 너무 많은 도메인의 기능이 생긴다고 생각할 수 있지만 이는 앱의 문제가 아니라 폴더를 적절하게 나눔으로써 해결할 수 있는 문제입니다.
앱을 나누지 말라는 의견이 아닙니다. 새로 개발하려는 기능이 의존성이 생기지 않고 재사용가능한 기능이라면 새로운 앱을 생성합니다. 단일 의존성으로만 기능을 구성하는 경우에도 앱을 나누는 것이 좋습니다. 판단에 경험이 필요하고 변경사항이 많이 일어나는 환경이라면 앱을 분리했다가 의존성이 생기면 합치는데 시간을 꽤 쓸 수 있습니다.
단일 앱을 사용함으로써 위에서 이야기한 두 가지 문제를 해결할 수 있습니다. 앱의 역할에 맞게 명확하게 사용할 수 있습니다. 의존성이 생기는 모든 것을 합쳐 하나의 앱으로 사용했기 때문에 모든 앱은 독립적으로 재사용 가능하고 키고 끄며 사용할 수 있습니다. 이전에 두 앱에서 공유하는 기능을 작성하려 할 때 어디에 위치해야하는지 고민할 필요가 없어졌습니다. 하나의 앱에 프로젝트의 규칙에 따라 두면 됩니다.
앱을 분리하지 않아 생기는 문제도 있습니다. 충돌을 해결하기 위해 더 많은 시간을 써야 합니다. 두 앱에서 따로 생성되던 마이그레이션을 이제 선형으로 유지하기 위해 시간을 써야 합니다. 또한 앱 내 도메인이 다르지만 동일한 이름을 사용하기 위해 위해 수동 작업이 필요할 것입니다.
참고 자료
- 단일 앱을 사용하는 오픈소스
https://github.com/getsentry/sentry
https://github.com/PostHog/posthog
- 앱간 의존성이 있는 다중 앱을 사용하는 오픈소스
https://github.com/Flagsmith/flagsmith
https://github.com/saleor/saleor
https://github.com/mozilla/addons-server
https://github.com/openedx/edx-platform
- 앱과 관련한 논의
'기술 > Django' 카테고리의 다른 글
프로덕션의 마이그레이션은 검토가 필요합니다 (0) 2024.01.18 Django 에서 N+1 쿼리 문제 예방, 발견하기 (0) 2022.01.25 Django Application 의 메모리 누수 해결하기 (0) 2022.01.25 'Settings' object has no attribute 'worker_state_db' (0) 2021.09.25 Django Rest Framework 의 APITestCase 에서 API 를 요청할 때 Body 데이터를 보내는 두가지 방법 (0) 2021.09.24