❐ Description
페이스콕(레슨 파트)를 처음 설계할 때 DDD(Layered)를 적용하기로 마음 먹었다.
이유는 과거에 위웃 프로젝트를 개발할 때 DDD를 점진적으로 적용하면서 많은 장점이 있다고 느꼈기 때문이다.
개발에 들어가기 앞서, 어떤 생각을 하면서 DDD 구조를 잡아가는지 기록하고 수정을 반복해보자!
❐ 프로젝트 이해하기
Bounded Context를 정하기 앞서, 해당 프로젝트의 기획과 비즈니스 플로우를 이해해야 했다.
기획서를 바탕으로 분석한 결과, 프로젝트의 목적을 다음과 같이 정의할 수 있었다.
베드민턴 레슨 예약 시스템을 제공하여
유저가 보다 쉬운 경로로 베드민턴을 배울 수 있게하자!
위 목적을 도출하는 과정에서 중요 키워드(레슨, 예약, 유저)를 3개 추출했으며, "예약"이라는 키워드를 통해
하나의 키워드를 더 추출할 수 있었다. 유저가 예약을 한다는 것은, 결제가 필수적으로 동반되어야 하는 행위다.
따라서 "결제"를 중요 키워드로 추가하였다.
❐ Bounded Context 정의하기
위에서 추출한 키워드를 Bounded Context로 정의해도 무리가 없다고 생각했다.
어떻게 보면 해당 키워드들이 프로젝의 중요한 덩어리가 된다고 생각했기 때문이다.
1. 추가 사항
회의 과정에서 비즈니스 모델로 구독을 추가하기로 결정됐다. 그렇다면 구독은 어디서 관리해야 할까?
고민끝에 별도의 Context로 정의하기로 결정했다. 이유는 다음과 같다.
1-1. Member-Context에 속해 있는 Coach Aggrregate의 하위 도메인
아무래도 현재 시점에서 구독은 Coach만 할 수 있기 때문에 이 방법도 고려를 해봤다.
하지만, `Coach`와 `Subscribe`의 생명주기 관점에서 바라봤을 때 적합하지 않다고 판단했다.
이와 마찬가지고 Payment-Context도 생각해볼 수 있긴 하겠지만, Payment-Context에 추가했을 경우
Payment-Context 역할의 명확성이 떨어지는 현상이 발생할 것이라고 생각했다.
1-2. 별도의 Context 정의
`Subscribe`가 별도의 로직을 가져야 되는것은 필수적이다. (예를 들어, 자동결제 라던지...)
무엇보다 `Subscribe`는 별도의 생명주기를 갖고 있기 때문에 별도의 Context로 뜯어내는게 맞다고 판단했다.
2. 정의하기 (last update: 2025.03.18)
그럼 이제 추출한 키워드를 바탕으로 Bounded Context를 정의하고, 각 목적도 정의하자.
컨텍스트 | 목적 및 역할 |
Member |
|
Lesson |
|
Reservation |
|
Payment |
|
Subscribe |
|
❐ 서로 다른 Context 간 협업은 어떻게...?
1. Reservation(registerCard) & Payment(settlement)
기획서에는 다음의 요구사항이 있다.
횟수제의 경우 당일 수업이 종료되는 시점에 정산을 하고,
기간제의 경우 등록한 기간이 만료되는 시점에 정산을 한다.
위 요구사항을 충족하기 위해선, `Reservation & Payment` 간 협력이 필요하다.
지금 당장 생각나는 건 Event를 발행해 협력하는 것이다. 협력을 하기 위해서 아래의 준비가 필요하다고 생각한다.
- 다른 Context 간 데이터 전송에 필요한 DTO 생성
- 서로 다른 Context이기 때문에, 다른 트랜잭션에서 작업을 진행
- 수업은 종료됐는데, 정산이 안되는 정합성 문제 대비
분명 수업은 종료 됐는데, 정산이 안되는 정합성 문제에 제대로 대비 해야할 것이다.
- 실패시 로직 재시도 처리(최대 횟수 설정 필요)
- 매일 자정 CRON을 통해 정산이 되지 않은 건에 대해서 batch 처리
- RabbitMQ 메시징을 통해, 메시지 무조건 1회 실행
❐ 서로 다른 Aggregate간 협업은 어떻게?
1. Facade layer 추가
횟수제 등록의 경우, 레슨 `예약 및 취소`시 등록카드에 잔여 수업 횟수를 갱신해줘야 한다.
비록 서로 다른 Aggregate지만 데이터 정합성이 굉장히 중요한 경우다.
이 경우 Spring 내부 Event를 발행해도 되겠지만, 복잡하지 않은 로직의 경우 비즈니스 로직을 한 눈에
파악하기 어렵게 만들 가능성도 있다고 생각한다.
따라서 복잡하지 않은 로직의 경우에는 Facade layer에서 두 Aggregate가 협력을 하는 것도 나쁘지 않다고
생각한다. 반면에 로직이 복잡하다면, Spring Event를 통해서 협력을 하는 방향으로 협력을 해보자!
'Project > 페이스콕' 카테고리의 다른 글
RabbitMQ 도입기 (0) | 2025.02.20 |
---|---|
SSH 터널링으로 private-subnet에 있는 RDS 접근하기 (0) | 2025.02.18 |
AWS SQS 도입기 (0) | 2025.02.14 |
API Gateway 구축하기 (0) | 2025.02.07 |
프로젝트 타임라인 (0) | 2025.01.13 |