NEXTSTEP에서 진행하는 교육과정 DDD 세레나데 2기다.
교육을 수강한 지 1년이 지났지만, 이제야 후기를 작성한다.
2주차 후기
2주차는 모델링을 주제로 유비쿼터스 언어, 바운디드 컨텍스트, 이벤트 스토밍을 배우는데 간단하게 설명하면
유비쿼터스 언어는 구성원이 사용하는 비즈니스 용어를 하나로 통일한 언어이며
바운디드 컨텍스트는 도메인 범위를 정한다고 볼 수 있다.
이벤트 스토밍은 비즈니스 도메인을 빠르게 탐색하고 학습하여 유비쿼터스 언어와 바운디드 컨텍스트를 정하는 데 큰 도움을 준다.
이번에 배운 내용은 DDD를 적용하는 회사가 아니더라도 적용할 수 있는 좋은 내용이다.
이벤트 스토밍으로 구성원간 서로 다른 관점을 해소시키고 통일시키는 과정은 앞으로 협업에 많은 도움을 주고
해당 결과물을 토대로 신규입사자에게 빠른 적응을 도울 수 있다.
꼭 장점만은 있는 것은 아니다. 같은 용어라도 바운디드 컨텍스트에 따라 의미가 달라질 수 있기 때문에, 컨텍스트에 따라 용어의 의미를 구분해야 한다.
1단계 - 용어 사전 만들기
요구 사항
- 키친포스의 요구 사항을 기반으로 용어 사전을 README.md에 작성한다.
- 한글명과 영문명, 간단한 설명을 표로 정리한다.
- 미션을 진행함에 있어 아래 문서를 적극 활용한다.
지난주에 작성한 요구사항으로 진행하는 미션이다.
요구사항의 단어를 통해 어떤 의미를 갖는지 용어 사전(유비쿼터스 언어)을 작성하는데, 개발자의 관점으로 프로젝트 내부에 용어 사전을 작성한다.
실제 현업이라면 비개발자도 볼 수 있는 곳에서 용어 사전을 작성하고 관리한다.
2주차 1단계는 진행속도가 빠르다, 요구사항으로 기반으로 용어 사전을 작성하기 때문이다.
용어 사전(유비쿼터스 언어)을 정의함으로써 얻는 장점 중 하나가 별도의 모델링 도구를 사용하지 않고 정의된 용어들을 코드에 그대로 녹일 수 있다.
현재 용어사전에서 코드에 작성하기 적절하지 않거나 어색한 영문명이 있으면 확인해보는 것도 중요하다. - 리뷰어
2단계 - 모델링
요구 사항
- 키친포스의 요구 사항과 용어 사전을 기반으로 README.md에 모델링을 한다.
- 설계한 것을 소리 내어 읽어 보고 말이 되는지 확인해 보는 것이 중요하다.
- 미션을 진행함에 있어 아래 문서를 적극 활용한다.
모델링을 진행하는 단계다.
SI/SM 시절, 모델링하면 개발자의 관점에서 데이터베이스 중심으로 ERD를 먼저 생각했었다. 이건 유비쿼터스 언어가 아닌 오로지 개발자만의 관점으로 작성된 모델로 비개발자는 이해하지 못했고, 비개발자한테 개발자의 관점으로 설명하는 문제가 있었다.
여기서 모델링이란 무엇일까?
기획자와 개발자 모두가 동일한 개념, 동일한 언어로 이야기하고, 애플리케이션이 무엇을 수행하는지 표현되는 모든 것이 모델링으로 볼 수 있다.
수첩에 끄적인 낙서, 한 줄로 적은 문장, 그림 등 구성원이 납득하면 모델링이다.
이전 단계에서 작성한 md 파일에 이어서 진행한다.
용어 사전처럼 한글명과 영문명을 둘 다 표기했다.
### 주문(`Order`)
- 주문(`Order`)은 주문 정보를 가진다.
- 고객이 선택한 주문 유형(`OrderType`)을 가진다.
- 고객이 확인할 수 있는 주문 상태(`OrderStatus`)를 가진다.
- 고객이 주문한 주문 메뉴(`OrderLineItem`)를 가진다.
- 주문이 들어온 주문 시각(orderDateTime)을 가진다.
- 주문이 배송(`DELIVERY`)일 경우 경우 배송 받을 주소(deliveryAddress)를 가진다..
- 주문이 매장내 식사(`EAT_IN`)일 경우 주문이 들어온 주문 테이블(`OrderTable`)을 가진다.
- 주문이 매장내 식사(`EAT_IN`)일 경우 주문 테이블(`OrderTable`)을 찾기 위한 주문 테이블 아이디(orderTableId)을 가진다.
- 주문 유형(`OrderType`)은 주문 유형 정보를 가진다.
- 배달 주문(`DELIVERY`)을 표현한다.
- 포장 주문(`TAKEOUT`)을 표현한다.
- 매장내 식사(`EAT_IN`)를 표현한다.
- 주문 상태(`OrderStatus`)는 주문 상태 정보를 가진다.
- 주문 대기(`WAITING`)를 표현한다.
- 주문 접수(`ACCEPTED`)를 표현한다.
- 주문 전달(`SERVED`)를 표현한다.
- 주문 배송 중(`DELIVERING`)를 표현한다.
- 주문 배송 완료(`DELIVERED`)를 표현한다.
- 주문 완료(`COMPLETED`)를 표현한다.
- 주문 메뉴(`OrderLineItem`)은 주문 메뉴 정보를 가진다.
- 주문 받은 메뉴(`Menu`)를 가진다.
- 주문 수량(Quantity)를 가진다.
- 주문 금액(Price)를 가진다.
... (생략) ...
위는 주문을 기준으로 진행된 최종 결과물 일부분이다.
최종 결과물이 되기까지 많은 어려움을 느꼈는데 가장 큰 문제는 무의식적으로 개발자의 관점으로 작성하게 된다는 점이다. 아래는 주문 모델링 초안이다.
개발자 중심적이고, 상세적이지 않아서 비개발자는 이해할 수 없는 표현력이다.
이를 수정하기 위해선 많은 노력이 필요했는데, 리뷰어의 도움이 컸다.
* 2단계가 끝나고 나서 다른 수강생은 어떤 표현을 했는데 한번 참고해보는 게 좋다.
3단계 - 기능 우선 패키지 구성하기
요구 사항
- 계층 우선 패키지 구조를 BOUNDED CONTEXT 중심의 패키지 구조로 리팩터링한다.
2주차 마지막 단계로 레이어 구조의 패키지를
이전까지 작업한 내용을 기반으로 바운디드 컨텍스트 중심의 패키지 구조로 변경하는 작업을 진행한다.
간단하게 생각하면 위의 모델링을 기준으로 분리만 하는 거다.
막상 분리를 진행하면서 도메인마다 서로 의존하는 게 많다 보니 여러 가지 행태가 떠 올랐다.
- [메뉴, 메뉴그룹] [상품] [주문테이블, 주문] 3가지로 패키지 구조를 나눠도 되지 않을까?
- [메뉴, 메뉴그룹, 상품] [주문테이블, 주문] 2가지로 패키지 구조를 나눠도 되지 않을까?
- 지금까지 진행된 작업내용에 따라 단순하게 분리하는 게 정답일까?
궁금해서 질문을 남겨봤다.
진행하면서 메뉴, 메뉴그룹, 상품, 주문테이블, 주문이 서로 연관되어 동작하는게 많다보니
[메뉴, 메뉴그룹] [상품] [주문테이블, 주문] 3가지로 나눠도 될거 같고,
[메뉴, 메뉴그룹, 상품] [주문테이블, 주문] 크게 2가지로 나눠도 될거 같아 보이네요.
그 외에도 생각하는 방식에 더 나눠지는 거 같아 생각할 수록 꼬여서 교육에서 진행된 요구사항과 모델링에서 정해진 컨텍스트를 기반으로 변경했습니다. 😣
그리고 PurgomalumClient는 특정 컨텍스트에 속하지 않고 다양한 곳에서 공용으로 사용되어 infra에 그대로 두었는데 옳은 생각이지 궁금합니다.
확인 부탁드립니다.
감사합니다!
다음과 같은 답변을 받았다.
좋은 고민 하고 계시네요 ㅎㅎ
요구사항과 모델링 관점에서는 글로 표현하다 보니 이상한 부분을 많이 못 느끼셨을 수도 있을 것 같아요.
그림으로 표현하고 각 컨텍스트간의 연관 관계를 나타내는 컨텍스트 맵을 그려보는 것을 권장드려요.
요구사항과 모델링은 프로젝트가 진행됨에 따라서 지속적으로 변경되고 관리를 해줘야 합니다
😄
답변대로 요구사항과 모델링 과정에서 이상한 것을 전혀 느끼지 못하고, 패키지 구조를 분리하면서 의존관계를 눈으로 확인하면서 의문이 생겼다.
또한 피드백으로 팁을 주셔서 가져왔다.
Menu, MenuGroup, Product, OrderTable, Order를 각 바운디드 컨텍스트라 정의하고 패키지를 구성 잘해주셨습니다.
Root Aggregate 기준으로 바운디드 컨텍스트를 나누어 주셨는데 저도 선호하는 방법이에요.
제가 패키지를 나누는 방법도 공유해드릴게요.
위 방법이 정답은 아니니 필요에 맞고 의미가 적절하게 패키지를 구성하면 된다고 생각해요.* domain : domain layer - aggreagte, repository, domain service 와 같이 도메인에서 처리하는 클래스들을 위치 시키는 편입니다. * application : application laeyr - 응용 서비스(application service)를 모아두곤 합니다. * api : presentation layer - controller, adaptor와 같이 외부 client의 요청을 받는 클래스를 모아둡니다. * infra : infrastructure layer - 이메일, 메시지 알림등과 같은 외부 서비스와 관련된 클래스를 모아둡니다. * dto - request, response, layer 간 데이터 이동을 위한 클래스를 정의합니다.
https://github.com/cheese10yun/spring-guide/blob/master/docs/directory-guide.md
https://en.wikipedia.org/wiki/Package_principles
https://medium.com/@ssowonny/package-by-feature-in-clean-architecture-projects-e14d25e3905e
http://www.javapractices.com/topic/TopicAction.do?Id=205
더 나아가 패키지간 의존성 관리 방법에 대한 고민이 생기기도 하는데 토스 컨퍼런스 SLASH 22 발표 영상을 참고하면 좋다.
'교육 및 인강 > DDD 세레나데' 카테고리의 다른 글
DDD 세레나데 1주차 - 도메인 주도 설계 이해 (0) | 2022.11.01 |
---|---|
DDD 세레나데 시작하면서... (0) | 2022.10.31 |