nuyeo / NestJsBasic

따라하며 배우는 NestJS
7 stars 0 forks source link

커머스 ERD 설계하기 #4

Open kakasoo opened 1 year ago

kakasoo commented 1 year ago

여기서 설명하는 커머스 ERD는 가장 대표적인 커머스들의 공통 특징을 묶으려고 하는 것이고, 디테일한 부분까지 챙기지는 못합니다. 하지만 대충 판매자, 구매자, 주문결제에 대한 각각 6개씩의 테이블만 트리로 잘 만들어둬도 웬만한 커머스 구조를 모방할 수 있습니다. 재밌는 점은 판매자, 구매자, 주문결제로 이어지는 이 세 가지 트리의 구조가 서로 똑같고, 시간 순으로 진행된다는 점이에요. 그럼 한 번 시작해보죠.

kakasoo commented 1 year ago

ERD 작성의 기본 이해

정규화에 대한 설명은 하지 않을 거고요, 여기서는 간단하게 하나의 원칙만 설명하겠습니다. 더 많은 쪽이 더 적은 쪽의 ID를 가진다. 커머스를 봐요, 판매자는 여러 개의 상품을 업로드하고 판매할 겁니다. 만약 더 적은 쪽인 판매자가 상품의 아이디를 가진다면 아래처럼 판매자의 정보가 계속 중복될 수 밖에 없을 겁니다. 그러면 이건 굉장히 비효율적인 구조가 되기 때문에 차라리 반대로 아이디를 주는 게 더 낫다는 겁니다.

판매자의 아이디 판매자의 이름 상품의 아이디
1 카카수 1
1 카카수 2
1 카카수 3
kakasoo commented 1 year ago

판매자 도메인

설명을 다시 하죠, 일단 구매자에 대한 거는 일절 생각하지 맙시다.

모든 걸 1:M의 계층 구조를 가지면 마치 트리와 같은 모습이 될 겁니다.

kakasoo commented 1 year ago

판매자 묶음 배송

하지만 위 설명에는 하나가 빠져 있는데 바로 묶음 배송입니다. 왜냐하면 커머스에는 배송비가 무료가 되는 조건이 있는데요, 그걸 표현하기 위해서는 판매자가 묶음 배송을 먼저 만들어야 합니다. 같은 박스에 담아서 배송할 수 있는 상품을 기준으로 한다고 생각하면 이해가 쉬운데요, 이 묶음 배송이 다시 상품을 여러 개 가지게 해야 합니다. 다시 설명하면 아래와 같은 구조가 될 겁니다.

다시 말하지만, 묶음 배송은 판매자가 배송비를 1번만 부과한다던가 하는, 배송비 기준을 정하기 위한 테이블입니다. 추가로 상품 옵션은 신발을 구매할 때 '신발끈'처럼 상품에서 선택적으로 구매 가능한 대상이며 절대 별도로 구매할 수 없는 것을 말합니다.

kakasoo commented 1 year ago

판매자 도메인 테이블에 추가되어야 하는 정보들

간단하지만 어쨌든 물건을 담고 전시할 수 있는 판매자의 도메인이 완성되었습니다. 이 구조가 이해되었다면 다음은 간단합니다.

kakasoo commented 1 year ago

구매자 도메인

구매자 도메인은 판매자 도메인에 있던 6개의 테이블, 그리고 그 트리 구조를 그대로 복사해서 옆에 그려주면 됩니다.

그대로 옮기고 아이디들도 다시 엮어주기만 하면 됩니다. 하지만 구매자 도메인에서는 가격을 계산하기 위한 각종 칼럼이 없습니다. 왜 일까요?

kakasoo commented 1 year ago

구매자 도메인의 계산 방법은 판매자의 영향을 받는다

장바구니 옵션, 장바구니 선택 옵션 등에는 가격 칼럼이 없습니다. 구매자가 장바구니에 물건을 담았다고 해도 판매자가 가격을 조정했다면 거기에 따라가야 합니다. 아직 구매를 한 건 아니기 때문에 구매자 도메인의 가격 관련 칼럼들은 모두 판매자 쪽으로부터 와야 합니다. 반대로 새로 추가되는 칼럼이 있는데 장바구니에 담은 상품의 수, 즉 수량에 대한 칼럼이 필요합니다.

kakasoo commented 1 year ago

주문 결제 도메인

주문도 똑같이 트리 구조를 그대로 옮겨보면 됩니다.

판매자 구매자 영수증
묶음 배송 장바구니 묶음 박스 단위 묶음
상품 장바구니 상품 결제된 상품
상품 옵션 장바구니 상품 옵션 결제된 상품 옵션
상품 선택 옵션 장바구니 상품 선택 옵션 결제된 상품 선택 옵션
상품 입력 옵션 장바구니 상품 입력 옵션 결제된 상품 입력 옵션

다만 추가된 게 있다면, 이번에는 결제가 된 것이기 때문에 결제된 당시의 가격과 수량을 저장해야 합니다. 판매자가 가격을 바꾸든 말든, 배송비 부과 정책을 바꾸든 말든, 이미 확정된 금액은 그대로여야 하고 취소와 환불도 당시의 가격대로 이루어져야 하기 때문입니다. 다시 강조하건대, 이번에는 바뀌면 안 되기 때문에 저장하는 겁니다.

kakasoo commented 1 year ago

부분 취소를 하면?

해당 상품이 없다고 가정하고 전체 가격을 다시 계산하면 됩니다. 이 때, 재계산은 주문 결제 도메인의 정보로만 이루어져야 하고 다른 테이블을 사용해서는 안 됩니다. 그렇게 해서 전체 계산을 다시 했다면, 이전과 이후의 가격을 빼는 것만으로 환불 금액, 취소 금액을 구할 수 있습니다.

kakasoo commented 1 year ago

배송비 무료 기준

꼭 번들 단위여야 하는가?

그런 건 아니고, 쿠팡처럼 유저의 등급, 회원에 따라 또 가격이 달라지는 경우가 있습니다. 이 또한 배송비를 일괄적으로 무료로 하는 경우도 있지만, 퍼센테이지를 달리 주는 등 차등이 있을 수 있습니다.

kakasoo commented 1 year ago

장바구니 아이디를 가지는 결제된 상품?

주문서 쪽의 결제된 상품상품 아이디를 가지는 거는 이해가 될 거에요. 상품이 여러 번 결제될 수 있기 때문에, 상품은 여러 개의 결제된 상품을 가지고, 그러면 당연히 상품의 아이디를 필요로 하겠죠? 그런데 장바구니 상품이 여러 개의 결제된 상품을 가진다고 한다면 그건 좀 이상해요. 결제가 여러 번 될 수 있는 장바구니가 있나? 놀랍게도 있습니다.

kakasoo commented 1 year ago

비즈니스적인 관점

설계는 항상 비즈니스적인 관점이 고려가 되어야 해요. 데이터가 많은 테이블은 수정 자체만으로도 많은 리소스를 쓰기 때문에, 설계에 많은 시간을 써야 하고, 당연히 그 기준은 비즈니스가 됩니다. 때로는 설계에 미친 개발자가 있을 것이고, 당장 급한 것만 처리하자고 말하는 개발자가 있을 텐데요 둘 다 공통점이 있습니다. 바로 입니다. 정상적인 개발자라면 돈에 대한 고민을 안할 수가 없고, 따라서 서로 다른 의견을 말하는 두 개발자는 같은 얘기를 하고 있을 겁니다.

개발자끼리 말이 다를 때는 어느 것이 돈을 더 버는지로 얘기하면 됩니다.

kakasoo commented 1 year ago

제가 가르치는 다른 분인데 참고하세요!

nuyeo commented 1 year ago

erd https://github.com/rimo030/Repo-Server/issues/14#issuecomment-1793816598 참고해서 ERD 생성했습니다.

✉ 질문

  1. 필수옵션에서 활성화상태는 어떤 것을 의미하나요?
  2. 판매자idnumber타입인 이유가 있을까요?
  3. 판매자이름은 왜 varchar(128)로 설정했나요? (이름이면 더 작게 해도 되지 않을까요)
kakasoo commented 1 year ago

제가 한 게 아니라 모르겠습니다. @rimo030 님이 답변해주시겠죠. :)

rimo030 commented 1 year ago
  1. 판매자가 옵션을 숨김 처리하고 싶을때 사용하는 용도입니다.
  2. 오타...입니다.
  3. 작성할 당시 DB의 용량을 어떻게 따져야되는지 몰라서 여기를 그냥 따라해서 그렇습니다....