들어가며
이번 글에서 설명하는 내용은 이희창님의 프로젝트 구조를 기반으로 도메인 계층의 structure를 구성할 때 최소한으로 필요하다고 생각되는 부분만 간추려낸 것이다.
도메인 계층의 structure은 크게 Entity 부, Service 부, DTO 부로 나뉜다.
(Entity 부, Service 부, DTO 부는 이해를 돕고자 필자가 부여한 용어이므로 큰 의미를 두지 않았으면 한다.)
도메인 계층 structure에서 각 부분이 하는 역할은 다음과 같다.
1. Entity 부
Entity 부에서는 도메인 객체의 속성과 매서드를 정의한다.
속성과 메서드의 예는 아래와 같다.
속성
- name
- age
- state
매서드
- enableState()
- disableState()
- Getter
- Setter
Entity 부는 크게 AbstractEntity와 도메인 객체로 나뉜다. 도메인 객체 만으로도 구현은 가능하지만, 프로젝트의 운영 및 유지보수를 위해 도메인에 공통적인 속성을 부여하기 위해 사용한다.
AbstractEntity
필자가 AbstractEntity를 이용해 구현한 내용은 도메인 객체의 생성 시각과, 수정 시각을 기록하는 것이다.
@Getter
@MappedSuperclass
//JPA JPA Auditing 기능을 이용하여 자동으로 시간 부여
@EntityListeners(AuditingEntityListener.class)
public class AbstractEntity {
@CreationTimestamp
private LocalDateTime createAt;
@UpdateTimestamp
private LocalDateTime updateAt;
}
도메인 객체
도메인 객체는 속성과 메서드를 정의하고, 앞서 언급된 AbstractEntity를 상속받는다.
2. Service 부
Service 부에서는 도메인 계층에서 제공해야 할 서비스를 정의하고 구현한다. 이 때 중요한 것은 코드를 읽었을 때 해당 도메인의 전체 흐름이 파악되어야 한다. 이를 위해서 다음과 같은 가이드라인을 따른다.
- 세세한 구현 및 low level 기술은 인프라스트럭처 계층에서 구현하도록 Interface로 정의한다. (Layered Architecture에서는 상위 계층이 하위 계층에 의존하지만, 도메인 계층이 모델의 업무 개념을 관리하기 위해 interface를 이용하여 의존성을 역전한다.)
- Service 간에 참조 관계를 두지 않는다.
값 객체나 엔티티 같은 도메인 객체에는 객체의 행동을 정의할 수 있다. 예를 들어 사용자 명으로 사용할 수 있는 문자열의 길이나 문자의 종류에 제한이 있다면 이러한 지식은 사용자명을 나타내는 값 객체에 정의될 것이다. 그러나 시스템에는 값 객체나 엔티티로 구현하기 어색한 행동도 있다. 도메인 서비스는 이런 어색함을 해결해주는 객체다.
-도메인 주도 설계 철저 입문 | 나루세 마사노부
도메인 서비스 인터페이스
도메인 서비스 인터페이스에서는 도메인 서비스에서 제공해야 할 요구사항을 정의한다.
도메인 서비스 구현체
도메인 서비스 구현체는 도메인 서비스 인터페이스에 정의된 기능을 구현한다. 이 부분에 도메인 기능의 흐름이 표시가 되어야 한다. 다만 기술적인 내용, 다시 말해 타 시스템의 호출이나 세부적인 구현에 대한 것은 Reader 서비스와 Store 서비스 인터페이스를 이용하여 인프라스트럭처 계층으로 넘긴다.
Reader 서비스 및 Store 서비스 인터페이스
Reader 서비스 및 Store 서비스 인터페이스는 JPA나 Spring JDBC, MyBatis등을 이용하여 도메인 기능에 대한 세부 구현해야 할 내용을 인터페이스로 정의한다.
강의에서는 Reader, Store 외에도 Aggregator, Executor등의 서비스 클래스를 나눌 수 있다고 설명한다. 이렇게 나누는 이유는 Service의 분량이 많아지게 되어 향후 코드 가독성을 해치는 것을 막기 위함이다.
3. DTO(Data Transfer Object) 부
DTO 부는 도메인 계층의 서비스가 인터페이스 계층, 인프라스트럭처 계층과 데이터를 주고받기 위해 정의한 DTO들을 의미한다. DTO부의 구성 요소는 Command와 Criteria, Info 다.
Command
Service의 입력 파라미터 중 생성, 수정, 삭제에 해당한다.
Criteria
Criteria는 DTO 부는 아니고, 조회과정에서 필요한 필터 객체를 의미한다. Comand 성 작업 파라미터(CUD)와 구분된다.
Info
Serivce의 출력 객체다. Database에서 조회한 Entity를 감싸서 다른 레이어로 전달한다.
구현 순서
프로젝트를 구현했던 순서는 다음과 같다. 이렇게 구현하면 계층의 의존성과 객체간 참조관계를 고려했을 때 유리하다. (프로젝트의 상황이나 조직에 따라 구현순서는 다를 수 있다.)
1. 도메인 계층에서 공통적으로 사용할 기능을 구현한다.
2. 도메인 계층에서 도메인 객체와 서비스를 구현한다.
3. 인프라스트럭처 계층에서 도메인 계층의 서비스 및 repository를 구현한다.
(Spring JPA 사용을 전제로 함)
4. 응용 계층에서 서비스 Facade를 구현한다.
5. 인터페이스 계층에서 Controller와 Listener를 구현한다.
마치며
이번 글에서는 도메인 계층을 구현하기 위해 참고한 구조에 대해서 정리해보았다. 지금까지 진행했던 프로젝트에 적용된 도메인주도설계의 내용을 설명하기 위해 강의 내용을 돌아보면서 다시한번 코드를 점검해보니 위의 내용과 상이한 부분들이 발견되었다 ... (수정해야겠군요.)
구현한 내용을 시각적으로 표현해 봤는데, 회사마다 구조는 상이할 수 있을 것 같다. 다른 도메인 주도 설계 책들에서 언급되는 structure도 이와 비슷하게 구성되어 있는 것으로 보이기 때문에, 만약 필자의 상황처럼 DDD를 적용하는 것이 처음이라면 괜찮은 구조인 것 같다. (더 좋은 구성에 대한 예가 있으면 공유 부탁드립니다 ㅠㅠ)
[1] 패스트 캠퍼스 MSA 강의자료 | 2021 | 이희창 | 링크
[2] 도메인 주도 설계 철저 입문 | 2022 | 나루세 마사노부 | 링크
'MSA 설계 & 도메인주도 설계' 카테고리의 다른 글
[MSA] 헥사고날 아키텍처(Hexagonal Architecture) (2) | 2022.02.21 |
---|---|
[MSA] 이벤트 스토밍(Event storming) (0) | 2022.02.15 |
[DDD] 인터페이스 계층과 응용 계층의 구현 (0) | 2022.02.07 |
[DDD] 애그리거트란? (0) | 2022.02.06 |
[DDD] 도메인 주도 설계의 계층 분리에 관하여 (0) | 2022.02.03 |