*'레이어드 아키텍처(Layered Architecture) feat.DDD' 에서 이어지는 아티클입니다.
A. 기존 아키텍처에서 생길 수 있는 문제점. (도메인 레이어의 중요성)
'레이어드 아키텍처' 아티클의 '레이어드 아키텍처의 계층' 파트를 보시면 계층간 높은 결합도 외에도 유지보수를 어렵게 만드는 것이 하나 더 있습니다. 아래는 문제의 파트인 레이어드 아키텍처의 Business Layer 에서 나타날 수 있는 문제들입니다.
문제 1. 하나의 도메인 서비스가 너무 많은 책임을 가지고 있습니다.
문제 2. Application Layer가 과도한 책임을 가져서 빈약한 도메인 모델(Anemic Domain Model) 안티패턴이 나타납니다.
둘다 결국 도메인 모델링의 문제인데, 도메인의 엔티티들이 책임 별로 잘 나누어 있지 못하면 비즈니스 로직의 확장과 유지보수가 어려워 질 수 있습니다. 레이어드 아키텍처같은 소프트웨어 아키텍처를 통해 시스템 레벨에서 계층간 유지보수와 변경이 쉬워질 수 있어도 비즈니스 로직은 경계가 무너지고 얽혀 있게 됩니다.
특히 문제 2번처럼 Application Layer의 책임을 과도하게 넓혀서 사용하게 되면 도메인이 아닌 응용계층에 비지니스 로직이 담기기 시작하면서 도메인의 클래스들은 단순히 DTO 정도로 이용 됩니다. 이 경우 객체 지향의 원칙을 지키지 못하고 비즈니스 계층의 코드는 결국 절차지향에 가깝게 구현됩니다. 마틴파울러는 이를 "transaction script" 형태라고 말하였습니다. (Martin Fowler, Microsoft)
DDD의 구현은 헥사고날 아키텍처를 이용할 수도, 클린 아키텍처를 이용할 수도, 레이어드 아키텍처를 이용할 수도 있습니다. 그러나 어느 아키텍처이든지 도메인을 중요시 하지 않고 개발을 하게 되면 시스템은 변경에 유연하더라도 비지니스는 변경에 취약한 코드를 만들 수 있습니다. 이를 막기 위해 DDD는 도메인 계층을 모델링하는 규칙을 지키도록 하여 각 아키텍처에서 효과적으로 도메인들을 격리시켜 도메인 끼리의 관심사의 분리와 느슨한 결합을 이루어 냅니다.
B. DDD 관점에서 레이어드 아키텍처 계층 구조
DDD는 도메인 계층을 가장 핵심 계층으로 봅니다. 그래서 인터페이스를 사용해 DIP(Dependency Injection Principal)을 적용하여 레이어드 아키텍처의 의존성 방향을 그대로 따르지 않고 인프라 계층이 도메인 계층을 의존하도록 합니다. 기존의 도메인 계층(상위)이 인프라 계층(하위)을 의존하던 상황이 반대가 되었습니다. 이를 통해 아무런 의존을 하지 않아 가장 변경에 영향을 안받는 계층이 가장 하위 계층 인프라 계층이 아니라 도메인 계층으로 변경 됩니다. 도메인 계층은 이제 인터페이스를 믿고 구현이 아닌 계약에 의존하여 자유로운 변경이 가능해 집니다.
이렇게 구성할 때 주의할 점은 인터페이스는 도메인 계층에 있어야 합니다. 위의 사진은 잘못된 예시를 보여 줍니다.
출처
Anemic Domain Models by John Mikael Lindbakk
Anemic Domain Model by Martin Fowler
DDD지향 마이크로 서비스 디자인 by Microsoft
JaeHoney님의 DDD-Infrastructure Layer 설계하는법
yoonbing9님 도메인 주도 설계의 계층화 아키텍처(Layered Architecture)와 DIP