2월 08, 2022

스타벅스 서비스 모델링

 https://www.starbucks.co.kr/menu/drink_list.do 

해당 페이지의 DB를 모델링 하는 것이 과제였습니다.

https://dbdiagram.io/home 툴은 해당 사이트를 활용했습니다. 

해당 페이지에서 구현해야 하는 사항은 음료카테고리영양 정보알러지음료 이미지음료 설명신상 여부 입니다



최종적인 결과는 이러합니다. 

제 1 정규화 법칙의 도메인 원자값을 만족시키기 위하여 반복 그룹을 제거한 테이블들을 만들었습니다. 

음료에 따라 매번 달라지는 음료이름,사진,설명,영양정보 를 drinks 테이블로 묶고.

카테고리 테이블과의 연결고리를 만들기 위하여 category_id 컬럼을 추가했습니다 

카테고리의 경우, 카테고리 하나에 여러 개의 음료가 연결되는 반면, 음료 하나에 여러개의 카테고리가 연결될 수는 없기에 1:N 관계입니다. 따라서 별도의 중간테이블 없이, category_id를 fk로 하여 category의 pk인 id와 drinks테이블의 category_id를 연결해주었습니다.


반면, 신상 여부알러지 는 다대다 관계입니다. 

하나의 제품에 여러개의 알러지 성분이 있을 수 있고, 알러지 성분 하나에 여러 제품이 연결될 수 있겠죠??

신상 여부의 경우, true or false로 구분되기에, drinks 테이블에 넣는 것이 맞는가에 대하여 고민을 했습니다.

그러나 drinks테이블에 넣을 경우 반복 그룹이 제거되야한다는 정규화 법칙에 어긋난다 판단했습니다. "신상"에 여러 제품이 연결될 수 있습니다. 그러나 "제품"에는 "신상" or "비신상" 만이 연결됩니다. 써놓고 보니 1:N 관계가 맞지 않나 싶습니다. drinks_id를 fk로 설정하고 drinks테이블의 id와 바로 이어주는 것이 맞는듯 합니다. 

일단 저희는 두 관계 모두 N:M으로 결론을 내리고 진행했습니다. 다대다 관계의 연결을 위하여 중간테이블을 만들어줍니다. 중간테이블의 경우에는 PK가 필요하지 않고, drinks 테이블과 isitNew/ allergy 테이블의 pk를 만들어줄 컬럼을 각각 두개씩 설정하고 이어줍니다.


개선할 점

  • 각각의 테이블들의 명칭은 django_tablenaming convention에 따라 복수형으로 쓰여야 합니다

근데 category allergy등은 는 복수가 아니라 단수입니다. - 복수로 바꿔주는 것이 맞습니다

drinks_istitNew의 경우에는 snake와 camel이 혼용돼 있기에 잘못된 naming입니다.

이러한 틀린 테이블명은 바꿔줘야 합니다

파이썬django의 약속에따라 테이블명은 모두 소문자로, 띄어쓰기는 snake case로 통일하면 됩니다.


  • drinks테이블의 drinksName , drinkImage, drinkDetail들의 이름은, drinks를 굳이 붙일 필요가 없습니다.

생각해보면, 나중에 이 아이들을 호출할 때, "drinks.drinksName"이런식으로 불러줘야하는데, drinks를 굳이굳이 두번씩 써준것을 볼 수 있습니다. 따라서 이러한 불필요한 반복을 막기 위해서라도, 테이블명을 굳이 앞에 붙여줄 필요가 없습니다. 그냥 name, detail이런식으로 작성하는게 더 효율적이고 맞는 표현입니다.


  • 그리고 웹 개발을 함에있어서 "info"이렇게 약어는 최대한 지양해줘야 합니다. information으로 전체 명칭을 작성해주는 것이 바람직합니다.


테이블의 구조의 경우,

  • drinkImage는 png는 파일의 확장자명이고, 보통 이미지 URL을 서버에 저장하기에 URL로 유형을 바꿔주는게 맞습니다

  • nutrition_info의 경우, 영양 정보에는 굉장히 많은 정보들이 담기기 때문에, 이에 대한 내용이 또 다른 테이블로 관리되는 것이 좋습니다.

이 별도의 테이블이 drinks 테이블을 물고 있다면, 더 확장성 있는 구조를 만들 수 있었을 겁니다. 이에 대한 모델 답안을 보겠습니다


nutrition이 별도의 테이블로 관리되는 것을 볼 수 있습니다.
nutrition이 drinks테이블에 내포된 지금의 구조를 사용하면 nutrition에 대한 불필요한 access가 많아지고, 데이터의 무결성에 손상을 줄 수 있습니다. 

  • 중간테이블의 경우에도 데이터 무결성과 효율성을 위해서 id로 PK를 주는것이 좋습니다. 저희의 ERD에서는 중간테이블에는 PK가 없습니다. 


참조  

위의 모범답안을 보면, 화살표가 있어서 참조의 방향을 나타냅니다. drinks는 categories를 무는(정참조), categories는 menu를 무는(정참조)합니다.

반대로 생각해보면, menu는 categories를 역참조(물려있다)합니다.

이러한 참조 개념은 어떻게 발생한 것일까요?

스타벅스 사이트를 보면, 음료, 푸드, 상품,카드 등은 MENU안에 포함돼 있습니다.


categories는 menu안의 하위 개념이라 볼 수 있습니다.

menu입장에서는 역참조된 일대 다 관계이고, menu가 "일" 인것입니다.

categories입장에서는 정참조된 일대 다 관계입니다. categories는 "다" 겠죠.

menu는 하나의 값만 있고, categories는 여러개가 존재합니다. 

마찬가지로 drinks는 categories를 정참조하고, categories는 drinks를 역참조합니다.

하위 개념이 상위개념을 정참조하고/ 상위개념은 하위개념을 역참조한다. 로 이해했습니다

drinks라는 수많은 음료가 category를 물기 위해서, drinks안에 category_id라는 FK를 둡니다. 

이 FK는 categories의 pk인 id를 뭅니다.

한마디로 fk가 정참조의 도착지의 pk값을 무는 것입니다. 

하위개념에 FK를 두고, 이를 통해 상위개념의 PK를 정참조합니다.



Decimal VS float
모범답안을 보면 영양정보처럼 소수점 값이 나오는 컬럼은 유형을 decimal로 설정한 것을 볼 수 있습니다. 여기에 float을 사용하면 안되는 걸까요??
decimal = 실수(numeric)과 동일 = 고정소수점
float = 부동소수점

고정 소수점 타입인 Decimal은 실수의 값을 정확하게 표현하기 위해 사용합니다.

즉, 소수부의 자릿수를 미리 정해놓고, 고정된 자릿수로만 소수 부분을 표현합니다.

DECIMAL(M, D)

M은 소수 부분을 포함한 실수의 총 자릿수를 나타냅니다, 최댓값 65입니다

D는 소수 부분의 자릿수를 나타내며, D가 0이면 소수부분을 가지고 있지 않다는 것입니다.

반대로 FLOAT 은 실수의 값을 대략적으로 표현하기 위해 사용합니다

FLOAT(P) : 이런식으로 정밀도에 필요한 최소한의 비트수를 명시할 수 있습니다. 

FLOAT에서 P는 0부터 24까지의 값을 가집니다. 

모범답안의 경우에는, 스타벅스의 커피를 먹는 고객 입장에서 정확한 영양정보값을 제공받는 것이 편리하기에 실수의 값을 정확하게 표현하기 위해 decimal을 사용한 듯 보입니다.