Skip to content

DDD를 따라간 멀티 모듈 구조

Sim-km edited this page Apr 5, 2024 · 9 revisions

지금까지는 DDD라고하면 도메인별로 패키지를 나누고 도메인 패키지 내부에 Controller, Service, Entity, Repository를 만드는게 다라고 생각했다.

하지만 도메인 주도 개발 시작하기라는 책을 읽으면서 DDD는 무엇인가? 과연 지금까지의 패키지 구조는 DDD 답게 만든것일까?라는 생각이 들었다.

그래서 이 프로젝트의 구조를 DDD에 맞게 구성해보려 한다.

DDD는 어떤 계층 구조를 가질까??

DDD의 계층은 presentation, application, domain, infrastructure 계층으로 구성되어있다.

이 계층을 대부분 Controller, service, (entity, repository), ? 로 생각할 것이다. 하지만 각 계층에 대한 설명을 보면 앞선 생각은 반은 맞고 반은 틀린것이다.

영역 설명
사용자 인터페이스 또는 표현(presentation) 사용자의 요청을 처리하고 사용자에게 정보를 보여준다. 여기서 사용자는 소프트웨어를 사용하는 사람뿐만 아니라 외부 시스템일 수도 있다.
응용 (application) 사용자가 요청한 기능을 실행한다. 업무 로직을 직접 구현하지 않으며 도메인 계층을 조합해서 기능을 실행한다.
도메인 (domain) 시스템이 제공할 도메인 규칙을 구현한다.
인프라스트럭처 (infrastructure) 데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다.

우선 presentation 계층과 application 계층은 평소에 생각하는 Controller와 Service가 위치하는게 맞다.

그러면 domain 계층과 infrastructure 계층은 어디에 사용하고 어떻게 구성해야할까?

Domain 계층

도메인 계층을 "시스템이 제공할 도메인 규칙을 구현한다."으로 설명하고 있다. 도메인 규칙이라는게 무엇일까? 우선 나는 이 도메인 규칙이라는 것을 비즈니스 로직 이라고 생각했다.

비즈니스 로직하면 Service가 떠오를 것이다. 맞다. 대부분의 비즈니스 로직은 Service에서 처리한다. 그렇다면 application 계층과 domain 계층 모두 Service가 존재하는 하는것인가라는 의문이 들 수 있다.

나는 둘 다 존재해야 한다고 생각한다. 하지만 하는 역할이 다르다고 생각한다.

application 계층은 "사용자가 요청한 기능을 실행한다. 업무 로직을 직접 구현하지 않으며 도메인 계층을 조합해서 기능을 실행한다."이라 설명하고 있기 때문에, application 계층의 service는 domain 계층의 service를 조합하여(Facade Pattern) 하나의 완전한 기능을 제공하는 역할을 하는 것이다.

그러면 Infrastructure 계층은 무슨 역할을 하는 것일까???

Infrastructure 계층

infra 계층은 이름은 들어봤지만 사용한 적이 별로 없는 계층이라 생각한다. 그 이유는 무엇일까?

우리는 대부분 domain 계층에 JPA 기술을 사용하여 특별한 구현 없이 데이터베이스에 접근하고 있다. 이렇게만 설명하면 infra 계층은 필요 없는거 아닌가라는 생각이 들 수 있다.

infra 계층을 "데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동을 처리한다."하고 설명하고 있다. 그렇다면 domain 계층에 JPA라는 기술이 녹아드는게 맞을까?

JPA라는 기술은 스프링 진영에서 많이 사용하고 바뀔 수 없는 부분이며 개발 편의성을 위해서라도 사용할 수 있는거 아닌가라고 생각할 수 있다. 하지만 JPA에서도 데이터베이스 유형에 따라 사용하는 애노테이션과 인터페이스가 다르다. 만약 데이터베이스가 변경되는 상황이 발생하면 모든 도메인 계층의 파일들을 수정해야한다. 이게 과연 옳을까? 나는 JPA는 infra 계층에 있어야 한다 생각한다.

그 외에도 infra 계층의 설명에 따라 외부 api를 호출하는 부분을 domain 계층에 인터페이스로 선언하고 이를 infra 계층에서 구현하는 방식을 사용해야한다.

DDD 구조 정리

그러면 각 계층을 파일 관점에서 설명하면 다음과 같다.

계층 설명
presentation controller
application domain 계층의 서비스를 조합하며, 때에 따라서 @Transactional 설정도 있음
domain 비즈니스 로직을 담당하는 계층, service, model, repository로 이뤄져 있으며, 외부 기술 없이 순수 자바 코드로만 이뤄져 있음
infrastructure jpa와 같이 구현 기술을 사용하는 계층

DDD 계층에서 사용하는 기술

또한 DDD를 따라간다면 각 계층에서 사용하는 기술이 정해지게 된다.

계층 설명
presentation spring web
application spring Transaction
domain x
infrastructure JPA, webclient...

DDD를 멀티모듈로 가져와보자

멀티 모듈 환경에 DDD를 도입한다면 앞서 말한 계층간의 구조를 패키지가 아닌 모듈 관계로 설정할 수 있으면, 각 모듈에서 사용할 수 있는 기술들을 제한할 수 있기에 멀티모듈 형식을 가져갈려 한다.

멀티모듈을 이용한 DDD 구조는 다음과 같다.

.
├── Api-Module # 스프링 실행과 presentation, application 계층을 담당하는 모듈
├── Common-Module
├── Domain-Module # 도메인들을 포함하는 모듈  
└── Infra-Module # 외부 데이터베이스 연결, API 호출을 담당하는 모듈

이렇게 (Presentation, Application)을 가지는 Api-Module, Domain 계층을 가지는 Domain-Module, 마지막으로 Infrastructure 계층을 가지는 Infra-Module로 구성하였다.

이를 통해 Api-Module와 Domain-Module에서 JPA 의존성을 가지지 않고 구성할 수 있게 됐다.

즉, 각 계층에서 사용하는 기술들을 제약할 수 있게 되었다. 또한 모듈간 의존관계 설정을 통해서 계층 의존이 역전되는 상황을 방지할 수 있게 되었다.