적당히 타협한 Django 아키텍처

Django는 아래와 같은 특성 때문에 클린 아키텍처와 DDD를 적용하기 어렵다. (프레임워크의 의도와 다르게 코드를 작성해야하는 경우가 생긴다.)

  1. 액티브 레코드 패턴을 사용하는 Model -> 도메인 모델로만 사용하기 어렵고 DB 테이블 구조와 밀접하게 연관
  2. 비즈니스 로직과 엮여있는 View -> 뷰에 비즈니스 로직을 구현하기 쉬운 구조
  3. Django ORM -> 데이터를 가져오고 저장하는 방식이 특정 ORM 코드에 종속됨

차선으로 DDD를 선택적으로 적용한 Layered 아키텍처를 생각한다. MSA로 확장 가능성을 고려해서, 적당히 타협한 아키텍처를 생각해본다.

  1. app 단위로 Bounded Context를 정의하고
  2. Domain Logic은 Model에 두고(Rich Domain Model)
  3. Service Layer(User cases)에 Application Logic을 분리한다.
    1. 도메인 객체 사용
    2. 엔티티 조회/저장
    3. 트랜잭션 보장
    4. 사용자 인증/인가
    5. 입력값 검증
    6. Domain Event의 Listener
    7. 로깅
  4. API 게이트웨이 패턴을 사용(또는 준비)한다. 게이트웨이 컴포넌트의 API에서 서비스의 API(또는 프로시저)를 조합한다.

DRF를 사용한다면 아키텍처의 혼란은 더 가중될 수 있다.

  • 시리얼라이저의 역할이 너무 많다. 원래 목적인 직렬화/역직렬화 외에도, 비즈니스 로직을 다루고 데이터 저장에 관여한다. 심지어 DRF의 뷰도 시리얼라이저에 강하게 종속되어있다.
  • 비즈니스 로직을 책임질 곳이 불분명하다. 아래 모듈은 각각의 이유로 (비즈니스 로직을 구현하기에) 적합하거나, 적합하지 않다.
    • Model - Django 설계 철학에 적합하나, Active Record 의 한계로 DDD 등 적용 어려움
    • View - 프레젠테이션 레이어로 기능하는게 이상적이나 역시 Django 특성상 비즈니스 로직을 포함하기 쉬움
    • Serializer - 코어는 데이터 직/역직렬화 기능이나, 편의를 위해 비대해졌다. 데이터 접근 및 저장하는 Repository, 입출력 형식을 검증하는 Validator, 심지어 request 객체를 다루는 Controller로서 쓰일 수도 있다. 어떤 형태로든 비즈니스 로직이 섞이기 쉽다.

refs