week1-1: 요구사항 나열해보기 feat. 도메인 주도 개발
프로젝트를 시작하기에 앞서 만드려는 사이트의 요구사항을 나열하고 아키텍처를 잡아보려고 한다.
1. '악기(상품)'를 '판매'하는 사이트
2. '유저'는 '관리자', '판매자', '일반'이 존재
3. '유저'는 '판매' '상품'을 '구매'하기 위해 '검색' 함
4. '검색'은 상품, 지역, 가격, 상태 등 '검색조건'이 존재
5. '상품'을 누르면 상세페이지에서 '구매'가 가능
6. '결제'는 '카드결제' 또는 '직접결제' 존재
7. '배송' 정보를 선택할 수 있음. '매장'에서 '배송'이 가능하다면 선택할 수 있음
8. '판매자'는 '매장'과 '상품'을 등록 할 수 있음.
그리고 ''안에 있는 것을 도메인으로 볼 수 있는지에 대해 GPT한테 물어봤다.
도메인을 어떻게 나누느냐는 **업무 모델(비즈니스 로직)**과 **데이터(엔티티)**를 어떻게 그룹화하느냐에 달려 있습니다. 말씀하신 식으로 ‘판매’, ‘구매’, ‘검색’, ‘결제’, ‘배송’, ‘유저’, ‘매장’, ‘상품’ 등을 각각 도메인으로 볼 수도 있습니다. 다만 실제 구현 단계에서, 너무 세분화하면 오히려 복잡해질 수 있고, 너무 크게 뭉뚱그리면 한 도메인에 로직이 과도하게 모일 수 있죠.
아래는 일반적인 전자상거래(이커머스) 관점에서 참고할 만한 도메인 분할 예시입니다. 각 항목 옆에, 질문에서 언급하신 “‘~’ 안에 있는 걸로 볼 수 있을까?”를 연결해드렸습니다.
1. 유저(User) 도메인
• 관리자, 판매자, 일반 사용자(구매자) 등의 **역할(Role)**을 포함
• 로그인, 회원가입, 권한 관리, 프로필 관리 등
(→ “‘유저’는 ‘관리자’, ‘판매자’, ‘일반’” 이라고 하셨으니, 이 부분이 User 도메인에 해당)
2. 상품(Product / Listing) 도메인
• 악기(상품) 등록, 조회, 수정, 삭제 등 CRUD
• “‘상품’을 등록” → 판매자가 올리는 매물(“판매”)
(→ “악기(상품)를 판매하는 사이트” 라고 하셨으니, 실제로는 Product나 Listing 같은 도메인으로 볼 수 있습니다. “판매” 로직과 연결되지만, 실제 도메인 이름을 Product로 두고 “등록/수정/삭제” 기능을 제공하는 식입니다.)
3. 매장(Shop) 도메인
• 판매자 중 ‘매장(인증 업체)’ 개념이 있을 경우 별도 도메인으로 구분
• 매장 정보(상호, 주소, 전화번호, 영업시간, 등록 상품 목록 등) 관리
(→ “판매자”가 개인뿐 아니라 “매장”일 수도 있다고 하셨으므로, 이 부분은 Shop 도메인으로 나눌 수 있습니다.)
4. 검색(Search) 도메인
• 상품, 지역, 가격, 상태 등 검색 조건을 관리하고 필터링, 정렬, 페이지네이션 제공
• 사실상 Product(또는 Listing) 도메인의 하위 기능으로 묶는 경우가 많지만, 검색 기능이 매우 중요하거나 고도화(예: ElasticSearch)될 경우 별도 도메인(또는 마이크로서비스)로 분리 가능
(→ “검색은 상품, 지역, 가격, 상태 등 ‘검색조건’이 존재”)
5. 주문(Order) 도메인
• “상품을 누르면 상세페이지에서 구매가 가능” → 구매를 실행하면 주문(Order)이 생김
• 결제, 배송 로직은 일반적으로 주문과 결합해서 다루는 편이 많음
예를 들어, Order 엔티티가 있고 여기에 결제 상태(결제 완료, 결제 대기 등)와 배송 상태(배송 준비, 배송 중, 배송 완료)를 연결하여 트랜잭션적으로 관리하는 식입니다.
(→ “결제는 카드결제 혹은 직접결제”, “배송 정보를 선택 가능”, “매장 배송 여부” 등)
6. 결제(Payment) 도메인
• 카드결제, 직접결제(계좌이체 등) 수단별 결제 로직 처리
• 결제 내역, 취소/환불 로직, 영수증 발행 등
• 규모가 커지면 Order와 분리해서 Payment를 독립 도메인으로 관리
(→ “결제는 ‘카드결제’ 또는 ‘직접결제’ 존재”)
7. 배송(Shipping) 도메인
• 배송지 정보(수령인, 주소, 연락처), 운송장(택배사, 송장번호)
• 매장 or 개인이 배송을 제공하는지 여부
• 배송 상태 추적(“준비 중”, “배송 중”, “배송 완료”)
(→ “배송 정보를 선택할 수 있음. 매장에서 배송이 가능하면 선택 가능”)
8. (선택) 관리(Administration) 도메인
• 관리자만 접근 가능한 기능: 사용자 관리, 상품 승인/차단, 통계(매출, 거래량) 등
• 일반적으로 User 도메인에 ‘Admin’ 권한이 있으면, 별도로 구분하기보다는 “Admin 전용 API”로만 구분하기도 함
실제 프로젝트에서의 정리 방식
1. User (역할: 관리자, 판매자, 일반)
2. Shop (매장 등록, 매장 정보 관리)
3. Product / Listing (상품 등록, 조회, 수정, 삭제, 검색필터)
4. Order (구매/주문 생성, 결제, 배송)
• 안에 Payment(결제) + Shipping(배송) 로직을 묶어서 관리
5. (옵션) Search(만약 검색을 대규모로 별도 처리 필요 시)
6. (옵션) Admin(관리자 대시보드, 통계, 권한 등)
일반적으로는 Order라는 큰 도메인에 “구매(Checkout) → 결제(Payment) → 배송(Shipping)” 절차가 한데 묶입니다. “판매”는 “누가 상품을 등록했는가?”라는 관점으로 Product(혹은 Listing)에 판매자 정보가 들어있다고 보기도 합니다.
정답 한눈에 요약
“필요한 기능을 나열해봤는데, 도메인을 ‘~’ 안에 있는 걸로 볼 때 이렇게 볼 수 있을까?”
네, 크게는 아래처럼 도메인을 잡으면 자연스러울 것입니다:
1. 유저(User): (관리자, 판매자, 일반 사용자)
2. 매장(Shop): (판매자 중 ‘매장’ 개념)
3. 상품(Product/Listing): (등록, 수정, 검색, 조회, 판매)
4. 주문(Order): (구매, 결제, 배송)
• Payment(카드/직접결제)
• Shipping(배송 여부)
5. (선택) 검색(Search) 도메인을 독립(혹은 Listing에 포함)
6. (선택) 관리자(Admin) 전용 도메인(또는 User의 권한 구분으로 처리)
위처럼 정리하면, 말씀하신 시나리오(악기 중고/새 제품 판매 + 결제 + 배송 + 검색 + 역할 분리)에 잘 부합하는 구조가 됩니다.
최대한 행동을 세분화 해서 나누었는데 시나리오 기준으로 적절한 도메인을 잘 뽑아주었다.
이를 바탕으로 백엔드 서버의 아키텍처를 잡아보았다.
- adapter영역은 바깥과 이어지는 영역이다. db와 연결되는 persistence와 controller가 있는 web으로 분류하였다. entity는 persistence에 있다.
- application 영역은 port에서 in/out interface를 정의해준다. 이를 바탕으로 adapter영역과 연결해주었다.
- application 영역의 service는 사실상 usecase가 될 것 같다.
- domain을 위를 바탕으로 나누었다. 그리고 DomainService를 만들었다. 기존에 Domain이 복잡한 기능을 가지게 되었을 때에 대한 고민을 했었는데 Domain Service를 Domain 영역에 넣어서 다루는 방법이 있다!
아키텍처는 앞으로 계속 수정될 것이다. 더 좋은 방법을 찾아서 :)