도메인 주도 개발 시작하기

송은우·2023년 1월 9일
0

도메인 주도 설계

목록 보기
1/1

개인적인 후기

API 를 설계할 때의 유사점

HttpAPI(대충 RestAPI의 제약을 다 따르지는 않는 설계) 의 EndPoint 하나를 통해서 여러가지를 동시에 변경할 수 있도록 일부러 만들었던 경우가 많았습니다

class ChoiceQuestion extends Question {
  constructor({ ...data }: CreateQuestionRequestDto) {
    this.data = data;
    this.validate();
  }

  private validate(): void {
    //Something
  }

같은 무언가가 있었을 경우, 조건에 따라서 추후 검증 로직이 변화할 수도 있고, 저장 방식이 바뀌는 상황이었습니다
이런 상황에서 세부사항을 직접 접근할 수 있도록 EndPoint를 만들 경우 데이터가 의도한 상황대로 쌓이지 않을 수 있습니다

이를 해결하기 위해서 EndPoint는 Question에만 열어두고, 그 세부 사항은 무조건 Question을 통해서만 접근하도록 API설계를 했던 상황이 있었는데, 어그리거트 루트와 되게 유사하게 사용했던 경우라고 생각합니다

Interface를 통한 DIP가 필요한가?

요즘에는 대부분의 테스팅 프레임워크가 클래스를 모킹할 수 있고, 메서드도 모킹할 수 있기에, 단순히 테스팅 용도로만 사용할 경우 커다란 메리트가 없다고 느껴지기도 함

2가지 장점이 생각나는데
1. 만약 단위테스트를 전체 애플리케이션의 로딩이 필요한 통합 테스트로 바뀌는 상황이 발생한다면 이런 부분에 있어서는 장점이 있을 수 있을 것이라고 생각함

  1. 또 다른 장점으로는 다른 구현체로 추후 변경을 대비한다는 점에서 의존성을 한 단계 끊어둔다는 장점
    다른 구현체로 변경이 될 수 있다는 점을 미리 생각한다는 점을 생각한다면 나름의 장점이 존재할 수 있음

상위 레이어에 인터페이스를 두는 이유가 뭘까

의존성의 방향이 물론 중요하다지만, 과연 그게 그렇게 중요한가? 라는 생각이 있었습니다

이때 자바의 멀티모듈 설계를 떠올리면 그 장점이 있다고 생각합니다

멀티 모듈시 패키지 의존성이 양방향이면 import가 안 되도록 설정이 되는 방식을 통해서 1차적으로 모듈의 의존성을 끊을 수 있다는 점이 커다란 장점이라고 생각합니다
만약 domain안에 repository 인터페이스가 없고, infrastructure 안에 있다면, domoain과 infrastructure안에 양방향 의존성이 생기기에, 관리하기 힘들 수 있습니다

Domain 부분에 infrastructure 코드가 들어간다고 보아야 할까?

https://techblog.woowahan.com/2637/
배민 멀티모듈 설계에서 domain부분이
repository, entity, 도메인서비스 이렇게가 들어간다고 적혀 있는데요

도메인 모델 속에 @Entity, @Embeddable 같은 코드가 무조건 들어갈 수밖에 없는 설계가 되는 경우가 많다고 생각합니다

이때 사실 infrastructure을 의존하고 있는게 아닌가? 라는 생각이 들 수도 있지만
infrasturcture 부분을 알아서 만들어주기에, 실제 작성할 필요가 없다는 점에서 infrastructure에 무조건 의존한다고 보기에는 살짝 애매하다고 볼 수도 있고

이 부분을 제거한다면 Entity 를 불러오고, 저장하는 과정이 너무너무 어려워지고, private을 통해 숨기기가 힘들어지는 경우가 많기에, 넣어도 된다고 생각합니다

애그리거트 루트

루트 단위에서 적절한 처리가 필요하다는 내용이 있음
그 내부 구현은 어떻게 되든 전혀 상관 없음

응용 계층에서 하나의 트랜잭션에서 여러 루트를 다루는 쪽이 더 깔끔할 경우가 많음. 한 애그리거트는 하나만 다루는 방향으로 작성

이때 팀 표준, 기술 제약, UI 구현의 편리일 때 다른 트랜잭션을 호출하도록 허용한다

이때 애그리거트단위로 조회시 장점이 db를 바꾸기가 쉽다
최적화 할 부분이 명확해지기에 다른 외부 구현을 어떻게 되든 상관없이 확실하게 보장한다는 장점이 있다

이때 로직이 응용 서비스 레이어로 가게 되는 문제가 있음
이를 팩토리를 통해서 래핑하는 것이 가능함

public class Store{
	public Product createProduct(ProductId newProductId, ProductInfo pi){
    	if(isBlocked()) throw
        return ProductFactory.create(new ProductId,getId(),pi)
    }
}

이때 애매한 부분이 생기는데, store 내부에서 검증 로직을 진행하는 과정을 거치지 않고, 바로 ProductFactory 를 호출해버리는 경우가 생길 수 있음

이런 식으로 문제가 될 수 있기에,
멀티 모듈이라면, product 모듈이 바깥에서 안 보이도록,
단일 모듈이라면 package private 같은 안전망을 두고
애그리거트 루트의 크기를 줄이는 쪽이 좋아보임

추후 더 알아보고 싶은 점

root
|-- my-parent
| |-- build.gradle
| |-- settings.gradle
| |-- module-a
| | |-- build.gradle
| | |-- submodule-aa
| | | |-- build.gradle
| |-- module-b
| | |-- build.gradle

멀티 모듈설계와 헥사고날 아키텍처를 동시에 적용한 프로젝트

profile
학생의 마음가짐으로 최선을 다하자

0개의 댓글