학부 시절 팀 프로젝트를 떠올려보면, 비슷한 배경지식과 같은 교수님의 수업을 공유했던 덕분에 소통이 비교적 수월했던 것 같다.
사용하는 용어가 어느 정도 통일되어 있었고, 그래서 각자의 생각을 설명하는 데 큰 장벽이 없었다.
우리는 어릴 때부터 같은 것을 보더라도 사람마다 다르게 이해할 수 있다는 걸 배워왔다.
그럼에도, 막상 요구사항을 정의하는 순간이 되면
이 사실을 안다 해도 오해를 막을 순 없단 걸 항상 체감한다.
우리는 서로의 설명을 다르게 해석하기도 하고, 방금 들은 내용을 놓치기도 한다.
그래서 우리는 상대의 의도를 정확히 파악하기 위해 머릿속으로 여러 가능성을 동시에 떠올리고,
내가 이해한 바가 맞는지 확인하기 위해서 예를 들고, 글로 정리하고, 한정된 어휘 속에서 가장 적절한 표현을 위한 단어를 고르기 위해 있는 힘을 다한다.
거기에 더해 ‘혹시 나만 다르게 알고 있는 건 아닐까?’ '내 표현이 또 다른 오해를 불러일으키지 않았나?' 불안하기도,
팀원들 사이에서 이해가 갈릴 때는 어떤 방향이 프로젝트에 더 적합한지 선택해야 하기에 자연스럽게 더 신중하고 치열해진다.
여러 팀 프로젝트를 경험해 오면서 기획이나 요구사항 분석을 할 때
“빨리 끝내고 개발이나 하고 싶다”는 말을 종종 들었다.
나도 예전에는 이 과정이 귀찮고 힘들고 빨리 지나갔으면 좋겠다고 생각했는데,
오늘 이 과정을 회고해보니 조금 다르게 느껴졌다.
그럼에도 불구하고, 팀원들과 같은 문제를 어떻게든 함께 해결해보자 고민하고 하나의 방향으로 맞춰가는 이 복잡하고 때로는 버거운 과정을 해결하는 것 자체가 개발자로서 꽤 멋진 부분 중 하나라고 느껴졌다.
그래서 무작정 힘들다고만 생각하기보다는,
앞으로는 이 과정 자체를 조금은 즐겨보도록 해야겠다!
발제문에서 주문 하나당 상품 한 종류만 다루도록 되어있다.

만약 주문 하나에서 상품 여러개를 다룬다면 어떻게 바뀔까?
Order (Aggregate Root)
├─ id (UUID)
├─ supplierId
├─ receiverId
├─ deliveryId
├─ orderItems (List<OrderItem>)
└─ requestDetails
OrderItem (Entity)
├─ productId (Product Context 참조, ID만)
└─ quantity
기존에 있던 productId quantity 를 OrderItem으로 빼서
Order에서 리스트로 관리하게 하고,
추후에 부분 취소,부분 환불, 부분 배송등을 다루게 된다.

허브배송담당자는 구간마다 다른 사람이 배정될 수 있어서 허브-허브'경로 기록' 단위로 담당자가 변동된다.
배달 과 생명주기를 같이 하지 않아 따로 뺐다.
-> 배송이 진행됨에 따라 허브간 경로 DeliveryRoute를 수정하고 그 안에 허브배송담당자를 둔다.
업체배송담당자는 최종 허브→업체 구간 전체를 한 명이 담당하기 때문에 배송 엔티티에 따라 고정되어 있다.
Delivery (Aggregate Root)
├── id (UUID) // delivery id
├── orderId // 주문 id
├── DeliveryStatus (Value Object)
│ └── HUB_WAITING | HUB_MOVING | HUB_ARRIVED
│ | COMPANY_MOVING | COMPANY_DELIVERED
├── originHubId // 출발 허브
├── destinationHubId // 도착 허브
├── recipientId // 수령 업체
├── companyDeliveryManagerId // 업체 배송 담당자
└──DeliveryRoute (Entity) // 한 허브에서 다른 허브간 이동에 대한 경로 테이블
├── sequence
├── originHubId
├── destinationHubId
├── estimatedDistance
├── estimatedDuration
├── actualDistance
├── actualDuration
├── RouteStatus (Value Object)
│ └── WAITING | MOVING | ARRIVED
└── hubDeliveryManagerId
배송 담당자 (허브 배송 담당자, 업체 담당자) 정보는 유저에서 관리되게 한다.

User (Aggregate Root)
├── id (UUID)
├── username
├── password
├── email
├── slackId
├── Role (Value Object)
│ └── MASTER | HUB_MANAGER | DELIVERY_MANAGER | COMPANY_MANAGER
└── Status (Value Object)
└── PENDING | APPROVED | REJECTED
DeliveryManager (Entity)
├── userId ← User와 동일한 ID
├── slackId
├── DeliveryManagerType (Value Object)
│ └── HUB_DELIVERY | COMPANY_DELIVERY
//└── sequence ← 배정 순번 (kafka 기본 라운드로빈 사용시 필요 없음)
원래 DeliveryManager의 경우 Aggregate Root로 두고, 따로 서비스를 빼려고 했다.
하지만 다음과 같은 고려사항으로 User 서비스에 두게 되었다.
User 정보와 생명주기를 비슷하게 가져간다
User엔티티의 Role이 DELIVERY_MANAGER 로 바뀔 때 생성되고, 해당 User가 삭제될때 같이 삭제되어야 한다.
User 정보 + 허브담당/업체담당 구분 필드만 있는 단순한 aggregate라서 배송 담당자 서비스를 구성하는 비용이 더 크다 생각해 굳이 빼지 않았다.
slackId정보도 User엔티티 정보와 같아 별다른 API/이벤트처리 요청없이 DB단위에서 같이 가져올 수 있다.
단, 이 때문에 keycloak을 사용하더라도 사용자 테이블을 추가해야하는 것 같다.

비즈니스 로직을 정했다.
