❯ DDD(Domain Driven Design) 도메인 주도 설계
Domain이란 하나의 비즈니스 업무 영역과 관계된 개념이다.
식당을 예로 들어보자. 주문을 하는 것 / 음식을 만드는 것 / 조리된 음식을 전달하는 것 등 각각의 기능이 하나의 도메인 지식이 되며
이를 구현한 것을 비즈니스 로직이라고 한다.
도메인 주도 설계는 이러한 도메인들을 위주로 진행되는 설계 기법을 의미하는데 여기에서 다음 두 가지 개념이 필요하다.
- Aggregate(애그리거트): 비슷한 업무 도메인의 묶음을 의미한다. 비즈니스 로직을 캡슐화하는것과 관련이 있다.
식당 예시를 활용해서 설명하면 고객 / 주문 / 메뉴(음식) / 결제 각각이 애그리거트가 될 수 있다.
애그리거트간의 관계는 1 : 1, 1 : N, N : N이 될 수 있다. - Aggregate Root: 하나의 Aggregate는 여러 도메인으로 구성될 수 있는데 그중 해당 Aggregate를 대표하는 도메인을 의미한다.
아래에서 고객애그리거트의 '고객정보', 주문 애그리거트의 '주문정보'가 Aggregate Root가 된다.
애그리거트 루트는 애그리거트 내의 다른 모든 도메인들과 직간접적으로 연결되어있다.
* 애그리거트 경계를 나누는 팁
도메인을 변경하는 주체가 다르다면 각각 다른 애그리거트에 속한다.
ex) 음식과 음식에 대한 리뷰 (음식 : 식당에서 관리, 리뷰 : 고객이 관리)
Spring Data JDBC를 사용하기 위해서는 먼저 ①데이터베이스 테이블 설계, ② 도메인 엔티티 클래스 설계를 해야 한다.
기본키/외래키 등을 사용해 테이블 간의 참조가 직관적으로 나타나므로 테이블의 구조를 파악하는 것이 상대적으로 쉽다.
따라서 구조 설계가 익숙하지 않다면 애그리거트 설계 -> 테이블 설계 -> 엔티티 설계 순서로 진행하는 것이 좋다.
① 데이터베이스 테이블 설계
데이터베이스 테이블 간의 참조는 외래키를 통해 이루어진다.
CREATE TABLE IF NOT EXISTS ORDERS(
ORDER_ID bigint NOT NULL AUTO_INCREMENT,
MEMBER_ID bigint NOT NULL,
ORDER_STATUS varchar(20) NOT NULL,
CREATED_AT datetime NOT NULL,
PRIMARY KEY(ORDER_ID),
FOREIGN KEY(MEMBER_ID) REFERENCES MEMBER(MEMBER_ID) -- 외래키를 통해 Member와 Orders가 연결된다.
);
② 도메인 엔티티 클래스 설계
도메인 엔티티 클래스 간의 관계는 객체 참조를 통해 이루어진다.
1 : N의 관계에서 여러 개의 객체를 참조할 수 있으므로 이 경우에는 List, Set 같은 컬렉션을 사용한다.
애그리거트 객체 간에 매핑을 할 때는 애그리거트 매핑 규칙을 준수해야 한다.
[객체 매핑 규칙]
1. 모든 엔티티 객체의 상태는 애그리거트 루트를 통해서만 변경할 수 있다.
이를 통해 애그리거트의 일관성을 지킬 수 있다.
(애그리거트 루트에서 규칙 검증 과정을 총괄하므로 도메인 상태를 바꿀 수 있는지 검증하는 과정을 일관되게 거칠 수 있음)
2. 동일한 애그리거트 내에서의 참조는 엔티티 객체 참조를 통해 이루어진다.
@MappedCollection(idColumn = "A", keyColumn = "B") 애너테이션을 사용해 객체를 연결해 준다.
idColumn 에는 자식테이블의 외래키에 해당되는 열을 입력하고, keyColumn에는 자식 테이블의 기본키에 해당하는 열 입력한다.
3. 애그리거트 루트 간의 참조는 ID를 사용한다.
예를 들어, Member 엔티티와 Order 엔티티 간에 1 : N 관계가 있다고 가정하자.
Order 엔티티 안에 memberId를 외래키처럼 추가해서 참조한다.
전체 흐름을 정리해 보면 애그리거트를 구분하여 애그리거트 루트를 찾고, 루트를 통해 엔티티 간의 관계를 규정한다.
그 이유는 Spring Data JDBC가 ORM 방식이기 때문이다. (객체 간의 상호작용)
오늘 학습 내용은 처음 강사님께서 말씀하셨던 것처럼 결코 쉽지 않은 내용이었다.
코드를 보고 치는데도 왜 이걸까? 싶은 부분이 많았고 필드명이 길고 복잡해서 헷갈리는 부분이 많았다.
결국 느낀 점은 각 엔티티 간의 관계가 어떤지, 메서드의 매개변수와 리턴타입이 어떤 것인지,
파라미터의 타입이 어떤 것인지 파악하는 것이 중요하다는 것이었다.
Set <>, List <>에 DTO까지 적용하니 비슷하게 생겼으나 전혀 다른 타입인 경우들이 많았다.
특히 참조 관계에 있는 객체들도 많아져서 코드를 대충 보지 않고 타고 타고 들어가면서 어떤 값들이 있는지 파악하는 게 중요한 것 같다.
그래도 강사님께서 야근까지 하시면서(!) 개념을 하나하나 다 설명해 주셔서 좀 더 이해가 된 것 같다.
'부트캠프 개발일기 > Spring MVC' 카테고리의 다른 글
49일차: JPA(Java Persistence API) (0) | 2023.04.21 |
---|---|
48일차: Pagination(페이지네이션) API (0) | 2023.04.20 |
46일차: Spring MVC(JDBC, Spring Data JDBC) (0) | 2023.04.18 |
45일차: Spring MVC(비즈니스적인 예외 던지기, throw) (0) | 2023.04.17 |
44일차: Spring MVC(예외처리) (0) | 2023.04.14 |