rimo030 / nestjs-e-commerce-frame

✏️ NestJS로 구현한 Commerce API
45 stars 1 forks source link

ERD #14

Open rimo030 opened 8 months ago

rimo030 commented 8 months ago
  1. Board Entity 포함 모든 Entity에는 createdAt, updatedAt, deletedAt 이라는 시간 값을 저장할 칼럼이 필요해요. 생성날짜, 수정날짜, 삭제날짜입니다.
  2. 생성날짜는 row 생성 시 현재 시간이 기입되도록 DB에서 default 값으로 NOW()를 넣어주어야 해요.이후에는 절대 값이 바뀌어선 안됩니다.
  3. 수정날짜도 default는 NOW()이며 수정 시마다 값이 바뀌게 default 값에 ON UPDATE 구문을 넣어주어야 합니다.
  4. 삭제날짜는 nullable한 칼럼입니다.
  5. DATETIME과 TIMESTAMP의 차이를 학습하세요.
  6. soft-delete에 대해 학습하고 왜 삭제날짜가 필요한지 설명해보세요.

이렇게 적용 및 추가 학습해보시고 커머스 ERD를 그려보세요. 이건 ERDCloud로 커머스 예제를 검색해보시고, ERDCloud나 drawio로 그림을 그려서 github issue로 올려주세요. 변경사항이 생길 때마다 논의할 수 있게 원본 파일도 항상 저장해주시고, ERD 그리는 법은 형식에 연연하지 말아주세요. "아직은"

Originally posted by @kakasoo in https://github.com/rimo030/Repo-Server/issues/13#issuecomment-1791740480


createdAt/updatedAt/deletedAt Column

NOW()를 사용해 현재 시간을 기입

  1. createdAt: 생성날짜 (변경되지 않음)
  2. updatedAt: 갱신 날짜 (변경 됨)
  3. deletedAt: 삭제 날짜 (NULL 허용)

DATETIME / TIMESTAMP

TIMESTAMP는 내부적으로 시간을 가져올 때 Timezone을 적용합니다. DATE DATETIME TIMESTAMP
Format YYYY-MM-DD YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss
Desc 날짜만 표기 날짜 및 시간 표기 날짜 및 시간 표기
기본적으로 NOT NULL
Timezone 기반
Supported 1000-01-01 ~
9999-12-31
1000-01-01 00:00:00 ~
9999-12-31 23:59:59
1970-01-01 00:00:01 UTC~
2038-01-1903:14:07 UTC
Storage 3 bytes 8 Byte 4 Byte

hard delete/soft-delete

데이터베이스에서 데이터를 삭제하는 방법에는 물리삭제(hard delete)와 논리삭제(soft delete)가 있다.

논리 삭제를 이용하는 이유는 삭제된 데이터를 추후에 사용할 가능성 (데이터복원 및 데이터 분석) 이 있기 때문이다.


kakasoo commented 8 months ago

커머스 장바구니 설계하기

시간 값을 왜 저장하는지 이해하기 어려울 거 같아서 제 생각을 정리해봤어요.

CASE 1. 유저 A가 물건을 장바구니에 담고 지웠다

이 두 케이스 중 정답을 알려면 구매 내역 테이블을 확인해서, 장바구니가 삭제된 시간에 맞춰서 구매 내역에 상품 아이디가 기록이 되었는지, 또는 구매 내역의 테이블에서 장바구니를 가리키는 아이디 값이 있는지를 체크하면 됩니다. DB 입장에서는 지운 거지만 실제 현실에서는 그게 장바구니를 비운 것인지 아니면 구매가 된 것인지 알 방법이 없기 때문에 다른 테이블과의 연관관계로 논리적으로 추론해야 합니다.

CASE 2. 유저가 관심이 없어서 지웠나?

그냥 실수일 가능성이 높습니다. 하지만 생성 날짜와 수정 날짜가 다르다면, 예를 들어 물건의 구매 수량을 변경하는 등의 액션이 취해졌더라면, 그건 실수가 아닐 수도 있을 거 같아요.

CASE 3. 한 달 후에 상품을 지웠다면?

유저에게 직접 물어보지 않는 이상 정답을 알 방법은 없어요, 하지만 대략적인 추론은 가능할 텐데, 다만 추론을 위해서도 밑작업이 필요할 거 같아요. 먼저 서버의 접속 기록을 저장해야겠죠? 로그만 있다면 유저가 장바구니에 물건이 담긴 사실을 인지하고 있는지 확인해볼 수 있어요. 만약 로그인 자체가 한 달만이라면 그 유저는 아예 잊고 있었을 확률이 높고, 로그인은 자주 했지만 장바구니를 보질 않았다면 오랜만에 장바구니 청소를 했을 뿐일지도 몰라요. 하지만 주기적으로 장바구니를 보고 있었다면 정말로 고민을 했을 확률이 높을 거에요.

추가적으로 동일 카테고리의 다른 물건을 넣고 빼기를 반복하고 있다면 장바구니에서 물건을 담고 빼는 데 걸린 시간이 5분이라고 하더라도 실질적으로는 그 이상 고민한 것으로 간주할 수 있을 거에요. 예를 들어 A, B, C 사의 노트북을 돌아가면서 넣고 빼기를 반복한다면 각각의 상품을 5분 고민했기보다는 노트북이라는 카테고리에서 15분을 고민하고 있다고 보는 게 맞지 않을까요?

CASE 4. 유저의 평균 고민 시간?

만약 평균적으로 ( 또는 중앙값으로 ) 5분을 고민하는 유저가 있다고 해봅시다. 그러면 이 유저에게 할인 쿠폰을 발급하기에 가장 적절한 시간은, 적어도 5분 이후는 아닐 거에요. 이 유저가 이미 물건을 포기했을 가능성이 높으니깐 고민이 길어지면서도 평균적인 고민 시간보다는 좀 이르게 쿠폰을 발급해야 해요. 하지만 너무 빨리 쿠폰을 발급하면 어차피 살 물건을 더 저렴하게 파는 꼴이 되버리겠죠.

kakasoo commented 8 months ago

유저와 멤버의 차이

비회원으로 구매한 사람은 우리의 유저가 아닐까요? 비회원으로 구매한 사람의 일절 없다면, 동일 인물이 비회원으로 100개의 물건을 산 걸 가지고 우리는 100명의 유저가 있다고 착각할 거고, 또 유저 당 거래액도 심한 경우 백분의 일로 착각하고 말 거에요. 그래서 아직 가입하지 않은 사람들을 유저로 칭하고, 회원가입을 한 사람을 멤버로 칭하든 해야 할 거에요.

유저에게도 코드를 발급하고 회원가입 없이도 임의의 코드 값으로 그 사람을 식별할 수 있게 만들어요. 그리고 언젠가 그 사람이 가입하는 시점에 맞춰서 멤버 테이블에 저장해요. 그러면 유저와 멤버를 연결지으면, 이 사람이 가입하기 전에 어떻게 활동해왔는지도 알 수 있고, 혹여 다른 유저 여럿이 사실 하나의 멤버라는 것을 추론해낼 수 있을지도 몰라요. 데이터는 이렇게 비즈니스에 굉장히 중요한 자산이라서 쉽게 삭제해서도 안 되고 미싱 링크를 만들어서도 안 돼요.

아하 모먼트 라는 개념은 개발적인 내용은 아니지만 알아두면 좋겠어요. 유저가 우리 서비스에 가치를 느끼는 순간을 의미하는데, 페이스북에서는 7명의 사람을 친구로 등록한 사람은 페이스북을 쓰게 된다고 해요. 당연한 얘기지만 SNS에 아무 친구도 없다면 굳이 할 이유가 없잖아요? 커머스도 물건을 5번 이상 구매해본 사람들은 우리 커머스를 계속 쓰더라~ 라는 식의 법칙을 발견할 수 있을지 몰라요. 그렇다면 어떻게든 5번 구매를 하게 만들기 위해서 회원가입 이후 5개 물건을 구입하기 전까지는 쿠폰을 발급해줄 수도 있겠죠? 개발자라고 무조건 실무 기술만 익힐 게 아니라, CS에 대한 근본적인 물음을 던질 줄도 알고, 비즈니스적인 역량도 있어야 한다고 생각해요. 특히 데이터베이스는 이 세 가지가 집대성된 것이기 때문에 더 더욱요.

rimo030 commented 8 months ago

커머스 ERD를 작성했습니다 !

image

kakasoo commented 8 months ago

https://github.com/rimo030/Repo-Server/issues/14#issuecomment-1792880203

공통 피드백

  1. 이미 아시겠지만 DB의 모든 칼럼은 스네이크 케이스를 사용해야 합니다. ( DB는 대소문자 구분을 못합니다. )
  2. enum 값으로 넣은 것들은 varchar라고 가정하겠습니다, enum은 사용하지 말아주세요.

테이블마다의 피드백

상품 도메인

  1. seller (판매자)에 추가적인 정보를 넣어주세요.
    • 판매자도 유저와 동일하게 이메일과 패스워드가 있다고 가정합니다.
    • 판매자도 자신의 상품을 수정하기 위해서 먼저 로그인을 해야 할 필요가 있습니다.
    • 판매자는 사업자 등록번호가 필요합니다.
  2. product_bundle (묶음배송기준)은 계산 방법 칼럼 명을 변경해주세요.
    • 최소 배송비 기준을 넣어주세요. ( 각 배송비는 상품에 담겨 있어야 합니다. )
    • 번들은 상품의 배송비들을 모아놓고 어떤 것을 상품 배송비의 대푯값으로 해야 하는지를 결정하는 엔티티입니다.
      • 얼마 이상 사야 하는가?
      • 몇 개 이상 사야 하는가?
      • 기준치를 달성하지 못했다면 최소 배송비인가 최대 배송비인가?
  3. 입력옵션은 반드시 입력해야 하는지 유무를 넣어주세요.
    • 해외 배송의 경우에는 '고유통관번호' 같은 게 있을 수 있습니다. ( 반드시 입력해야 하는 정보 )

장바구니 도메인

  1. 장바구니 옵션과 필수 옵션에는 수량을 넣어주세요.
    • 동일 상품, 동일 옵션을 넣은 경우에는 합산되어야 합니다. ( 서버 로직 )
  2. 장바구니의 입력 옵션에는 사용자가 입력한 값이 담겨 있어야 하기 때문에 value 칼럼이 필요합니다.

결제 도메인

  1. 장바구니와 주문된 상품 테이블도 연결해주세요.
    • 어떤 장바구니로부터 결제가 되었는지 파악하기 위함.
    • 바로 결제는 즉시 장바구니에 담고 결제하는 형태로 동작해야 합니다. ( 또는 null 인 경우에는 바로 결제한 것으로 간주합니다. )
  2. 구매된 입력 옵션에서는 name과 title이 너무 모호하기 때문에 title은 value로 바꿔주세요.
kakasoo commented 8 months ago
rimo030 commented 8 months ago

Comment를 바탕으로 ERD를 수정하였습니다!

image

https://github.com/rimo030/Repo-Server/pull/19#discussion_r1382491588 type length 대한 자료는.. 배달의민족 ERD 를 참고하였습니다.


https://github.com/rimo030/Repo-Server/issues/14#issuecomment-1793331530

☑️enum

✅id

✅상품 도메인

✅장바구니 도메인

✅결제 도메인

kakasoo commented 8 months ago

추가적으로 Common table을 만들고 createdAt, updatedAt, deletedAt은 모든 테이블에 넣을 거라고 명시해주는 게 ERD가 더 깔끔할 거 같긴 합니다.

Question

rimo030 commented 8 months ago

https://github.com/rimo030/Repo-Server/issues/14#issuecomment-1793760650

네 추가적으로 테이블과 칼럼을 추가하였습니다!

image

이를 바탕으로 #19 Entitiy를 수정하겠습니다.

rimo030 commented 8 months ago

image

오타수정했습니다..