도메인이란?
도메인은 유사한 업무의 집합이다.
우리가 온라인 A제품을 구매하는 프로세스를 예를 들어보면, 먼저 A제품을 구매하기 위해서는 검색을 하게 된다. 원하는 A제품을 찾은 후 장바구니에 담을 수도 있고, 바로 구매할 수도 있다. 구매를 클릭했을 때 회원가입이나 비회원 구매 중 선택하고 배송 정보를 입력하게 된다. 구매 전 A제품에 대한 리워드나 할인 쿠폰을 적용할 수 있으며 구매 시 결제 방법을 선택하게 된다. 구매가 완료한 뒤에 가입된 회원인 경우 구매한 A상품에 대한 적립이 가능할 수 있으며 배송 추적 기능도 가능할 수 있다.
이 프로세스에서 서비스가 제공해야할 부분은 상품 조회, 회원, 결제, 장바구니, 구매, 배송 추적, 적립, 쿠폰으로 나눌 수 있다. 이러한 해결하고자 하는 문제 영역을 도메인이라 한다.
DDD(도메인 주도 설계, Domain Driven Design)란?
앞서 언급한 도메인을 나누어 설계하는 방식이다.
예로 들었던 A제품을 구매하는 프로세스에서 제공해야할 부분을 나눴는데 이것을 도메인으로 본다면 도메인을 기준으로 나눠서 설계를 하는 방식을 말한다.
DDD 목표
- 기존의 어플리케이션 설계가 도메에 대한 이해가 부족한 상태에서 설계 개발 되었다는 점을 개선하기 위해 등장하였으므로 현업과 개발자와의 양방향 커뮤니케이션이 핵심이다.
- 비즈니스를 도메인 별로 나누어 설계를 하여 확장성을 고려하고 모듈간의 의존성은 최소화하고 응집성은 최대화하는 것이다.
- 소프트웨어 엔티티와 도메인 컨셉트를 가능한 가장 가까이 일치시키는 것이다. 분석 모델과 설계가 다르고 그것과 코드가 다른 구조가 아니라 도메인 모델부터 코드까지 항상 함께 움직이는 구조의 모델을 지향하는 것이 DDD의 핵심원리이다.
- 모든 도메인에 용어를 맞추기 위해 모호한 단어를 쓸 필요가 없다. (보편 언어 - ubiquitous language)
MSA랑 무슨 상관관계?
Monolithic Architecture에서 Microservice Architecture를 분리하는 방법중 하나로 알려져 있다. DDD의 설계 원칙대로 MSA에 적용하면 도메인은 하나의 microsevice가 되며 각 도메인의 비지니스 로직을 고려해여 microservice의 설계 방식이 달라질 것이다.
도메인 모델
도메인 모델은 특정 도메인을 개념적으로 표현한 것이다. 도메인 모델을 사용하면 여러 관계자들과 동일한 도메인을 이해하고 지식을 공유하는데 도움이 된다. 모델의 각 구성요소는 특정 도메인을 한정할 때, 비로소 의미가 완전해진다. 따라서 각 하위 도메인마다 별도의 모델을 만들어 준다.
- Entity - 식별자가 존재하는 모델
- Value Object - 식별자가 필요없는 불변의 모델
- Aggregate - 생명주기가 동일한 모델을 모아놓은 Root 모델
- Service - 연산을 처리하는 모델
- Repository - 모델을 저장하는 곳
- Factory - Entity나 Aggregate을 생성하는 모델
예를 들어보면, 비회원제 주문을 Aggregate으로 가정해보자.
public class Order{
private long orderNo;
private Money price;
private Shopper shopper;
private List<Product> products;
public Order(Money price, String name, String address, List<Product> products){
this.price = new Money(price.getValue());
this.products = products;
this.shopper = new Shopper(name, address);
}
public addProduct(Product product){
this.products.add(product);
this.price = this.price.add(product.getPrice().getValue())
}
public updateShopperAddress(String address) {
this.shopper.updateAddress(address)
}
}
public class Money{
private int value;
public Money add(int value){
return new Money(this.value + value);
}
}
public class Shoppper{
private long id;
private int name;
private int address;
public updateAddress(String address) {
this.address = address;
}
}
Order내에 있는 Money는 ValueObject로 변경이 필요할때마다 새로 생성된다.
Shopper는 식별자를 보유한 Entity이지만 Order가 생성될 때만 생성되고 Order가 삭제될 때 함께 삭제된다.
이와 같이 Aggregate 내에 소속된 모델은 생명주기를 같이 한다.
Layered Architecture
일반적으로 어플리케이션 아키텍쳐를 4가지 레이어로 분류한다.
- User Interface - 사용자의 요청 전달
- Application - 비지니스 로직 레이어
- Domain - 도메인 모델을 구현(도메인 모델에 관한 로직)
- Infrastructure - 영속성을 구현하거나 외부와 통신을 제공
그림과 같이 상위 레이어에서 하위 레이어의 의존은 허용하고 있으나, 하위레이어에서 상위레이어의 의존은 허용하지 않는다.
바운디드 컨텍스트(Bounded Context)
바운디드 컨텍스트(Bounded Context)는 모델의 경계를 결정하며 한 개의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다. 바운디드 컨텍스트는 실제로 사용자에게 제공하는 물리적인 시스템으로 도메인 모델은 이 바운디드컨텍스트 안에서 도메인을 구현하게 된다.
바운디드 컨텍스트는 도메인 모델링을 할 때 중요한 역할을 하며 도메인 모델링을 할 때는 전체 도메인을 작은 단위로 분리하여 각 바운디드 컨텍스트를 식별하고, 각 컨텍스트가 독립적으로 동작하도록 설계한다. 이를 통해 전체 시스템의 복잡성을 줄이고 유연성을 높일 수 있다.
결론
DDD는 MSA를 하면서 반드시 알아야할 개념이다. 실제로 DDD를 적용한 MSA 프로젝트를 해본 결과 어려운 개념이라 적용하지 쉽지 않았고, 개발을 하던 도중에도 DDD 개념에 맞는 방식인지 계속 찾아보면서 개발을 진행하였다. 또한, DDD 개념을 수행하면서 추상화와 layered를 지키위해서 코딩을 해야할 양이 매우 많아져서 생산적이라고 생각이 들진 않았다. 그렇지만 DDD를 적용함에 따라 의사결정이나 관리 측면에서는 이점도 있었다.
'Tech' 카테고리의 다른 글
[MSA, Kafka] 공통 데이터 셀프컨테이닝? (2) | 2025.04.14 |
---|---|
[MSA, Spring] Multi-Redis? (2) | 2024.11.09 |
[MSA] 이벤트기반 아키텍처(Event-Driven Architecture) (0) | 2024.02.26 |
[MSA] Saga 패턴 관리 (0) | 2024.01.08 |
[MSA] 마이크로서비스 아키텍처(Microservice Architecture) 등장 (0) | 2023.12.19 |