웹 프로그래밍/[ Spring Boot ]

[ SpringBoot ] 10. DDD: 도메인주도설계

kim.svadoz 2021. 10. 20. 14:54
728x90
반응형

DDD: 도메인주도설계

객체지향의 핵심은 무엇일까?

객체지향에서의 핵심은 실세계의 객체(물건, 사람, 주문, .. 주도적으로 뭔가 생산할 수 있는 주체) 들이 서로간의 상호작용을 바탕으로 책임,협력,역할의 관점을 가지고 메세지를 교환하는 것이다.

객체지향의 핵심은 결국 객체(무언가를 만드는 주체)라고 할 수 있다.

그렇다면 어떤 객체가 필요한지 알 수 있고 어떻게 이 객체들을 추려내서 상호작용할 수 있을까?

이를 해결할 수 있는 것이 바로 도메인 주도 설계(DDD: Domain Driven Design)이다.

 

다시 말해서, 도메인을 중심으로 설계해 나가는 것이다.

도메인이란 실세계에서 사건이 발생하는 집합이라고 생각하면 쉽다.

쇼핑몰을 예로 들면,

쇼핑몰에서는 손님이 주문하는 도메인(Order Domain)이 있을 수 있고,

점주입장에서 옷들을 관리하는 도메인(Manage Domain)이 있을 수 있고

쇼핑몰 입장에서 월세, 관리비 등 건물에 대한 관리를 담당하는 도메인(Building Domain)이 있을 수 있다.

이러한 여러가지 도메인들이 서로 상호작용 하며, 설계해 나가는 것이 도메인 주도 설계이다.

 

DDD의 특징은 같은 객체(Object or Class)가 여러 개가 존재할 수 있다는 것이다.

주문 도메인에서 옷은 손님들에게 팔기 위한 객체 정보(name, price, ...)를 담고 있지만,

옷을 관리하는 도메인에서는 옷은 점주 집장에서 관리하기 위한 객체정보(madeTime, size, madeFrom, ...)를 위주로 담고 있는다.

 

다시 말해서 문맥(Context)에 따라 객체(Object)의 역할이 바뀐다는 것이다.

image-20211007102443192

Bounded Context는 Domain-Driven-Design의 중심 패턴이다. 대규모 모델과 팀을 다루는 것이 DDD의 설계 초점이다.

 

DDD는 큰 모델을 서로 다른 Bounded Context로 나누고 상호관계를 명시하여 처리한다.

Bounded Context에 따라서 모델들의 역할은 완벽히 달라지고, 책임 또한 달라지게 된다.

이는 Aggregate의 명시적 경계가 된다.

그래서 이를 외부로(public) 노출시키지 않고, package-private하게 내부에서만 알 수 있게 해야 하는 것이다. 이러한 관점을 더 나아가 직접 서비스에 적용한 것이 바로 MircorService이다.

다시 말해서 서로 다른 도메인 영역에 영향을 끼치기 위해서는 API로 호출을 해야 하는 것이다.

 

즉, 각각의 도메인은 서로 철저히 분리되고, 높은 응집력과 낮은 결합도로 변경과 확장에 용이한 설계를 얻게 될 수 있다.

그러면 어떻게 도메인 주도 설계를 구현할까?

image-20211007104326258

크게 3가지 Layer로 구분하는 것이 핵심이다.

  1. Application Layer
    • 주로 도메인과 Repository를 바탕으로 실제 서비스(API)를 제공하는 계층
    • 다른 시스템의 애플리케이션 계층과 상호작용 하기 위해 필요한 계층
    • 따라서 비즈니스 규칙이나 지식은 포함하지 않고 로직을 직접 수행하기보다는 도메일 모델에 로직 수행을 위임하는 역할이다.
    • 트랜잭션을 처리하고, 도메인 영역에서 발생시킨 이벤트를 처리하는 역할을 한다.
  2. Domain Layer
    • Entity, VO를 활용해 도메인 로직이 진행되는 계층
    • 이 계층이 도메인의 비즈니스 로직의 핵심이 되는 계층이다.
  3. Infrastructure Layer
    • 엔티티에 있던 데이터가 데이터베이스나 기타 영구 저장소에 유지되는 방식으로 외부와의 통신(ORM, DB) 및 외부 기술, 라이브러리를 담당하는 계층
    • 도메인 계층을 오염시키지 않아야 하고 프레임워크에 대한 고정 종속성을 지양함으로써 도메인 모델 엔티티 클래스는 데이터 유지에 사용되는 인프라와는 무관하게 유지해야 한다.

여기서 맨 앞단에 추가로 사용자에게 화면을 보여주고 세션을 관리하는 Presentation Layer(Controller)가 추가되기도 한다.

 

각각의 도메인들을 위와 같은 Layer로 철저하게 분리해서 만드는 것이 DDD의 핵심 설계 방식이다.

이렇게 설계한 도메인들을 모듈(Module)별로 분리하는 것이 마이크로서비스(MicroService).

핵심은 결국 도메인을 서비스 별로 분리하는 것!

하지만 모든 도메인에서 많은 객체(Object or Class)들을 다루고 있다면, 유지보수나 확장에 어려움이 있을 수 밖에 없다.

객체간의 상호작용은 점점 복잡해지고, 어떤 객체가 도메인을 대표하는 객체인지 혼란이 오기 때문이다.

 

그렇다고 엔티티 객체마다 Repository를 만드는 것은 마이크로 서비스의 장점이 희석된다.

여기서 등장하는 것이 바로 집합(Aggregate)이다.

image-20211007105622950

쉽게 얘기하면, 각각의 도메인 영역을 대표하는 객체가 바로 Aggregate이다.

이렇게 집합으로 나누게 되면, 각각의 도메인에 Repository로 묶어야 하는 객체(Entity)가 명확해질 수 있다.

Top-Down 방식으로 계층을 타고타고 내려갈 때 어떤 Entity를 만들기 위해 도메인이 이루어져 있는지 명확하게 들어오기도 한다.

 

위 예시에서는 Order라는 Domain에서 Order라는 Entity를 만들기 위해 다양한 객체들(Object or Class)이 상호 협력하고 있는 관계로 볼 수 있다.

이 Aggregate를 명확하고 잘 설계하는 것이 핵심이며 중요한 과제이다.

참조

https://martinfowler.com/bliki/BoundedContext.html

https://huisam.tistory.com/entry/DDD

728x90
반응형