[Database] 스타벅스 음료 페이지를 이용한 DB 모델링 연습 - 1

ybear90·2020년 2월 20일
2

Database

목록 보기
1/2

스타벅스 공식 홈페이지(or 사이렌오더 앱 중 일부) 를 참고하고 django framework를 이용하여 back-end api에 필요한 DB를 구성하는 연습을 하고 그 과정을 기록해 보았다.

DB모델링 구성하기

DB모델을 구성하기 위해 사용한 툴은 aquerytool로 초심자도 다루기 쉽게 되어 있다(링크참조) 해당 툴을 이용하여 아래와 같이 DB모델을 작성하였다

해당사진이 작게 나와 잘 안보일지 모르겠으나 위의 모델을 토대로 아래와 같이 models.py를 구성해 주었다 화살표 방향만 유의

from django.db import models

# Create your models here.

class Drink(models.Model):
    category            = models.ForeignKey('Category', models.SET_NULL, blank=True, null=True)
    datail_category     = models.ForeignKey('DetailCategory', models.SET_NULL, blank=True, null=True)
    name                = models.CharField(max_length=45)
    name_eng            = models.CharField(max_length=45)
    introduction        = models.CharField(max_length=500)
    size                = models.ManyToManyField('Size')
    nutrition           = models.ForeignKey('Nutrition', models.SET_NULL, blank=True, null=True)
    allergic            = models.ManyToManyField('Allergic', through='DrinkAllergic')
    img_link            = models.URLField(max_length=500)
    desc                = models.CharField(max_length=500)

    class Meta:
        db_table = 'drink'

class Category(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        db_table = 'category'

class DetailCategory(models.Model):
    name        = models.CharField(max_length=50)
    category    = models.ForeignKey('Category', models.SET_NULL, blank=True, null=True)

    class Meta:
        db_table = 'detail_category'

class Size(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        db_table = 'size'

class Nutrition(models.Model):
    kcal_per_one    = models.DecimalField(max_digits=5, decimal_places=1)
    sodium          = models.DecimalField(max_digits=5, decimal_places=1)
    saturated_fat   = models.DecimalField(max_digits=5, decimal_places=1)
    sugars          = models.DecimalField(max_digits=5, decimal_places=1)
    protein         = models.DecimalField(max_digits=5, decimal_places=1)
    caffein         = models.DecimalField(max_digits=5, decimal_places=1)

    class Meta:
        db_table = 'nutrition'

class DrinkAllergic(models.Model):
    drink    = models.ForeignKey('Drink', on_delete=models.SET_NULL, null=True)
    allergic = models.ForeignKey('Allergic', on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = 'drink_allergic'


class Allergic(models.Model):
    desc = models.CharField(max_length=50)

    class Meta:
        db_table = 'allergic'

먼저 실제 상품 대상인 Drink클래스에 대해 다음과 같이 ForeignKey를 정의해 주었는데, nutrition, category, detail_category로 각각 지정해 주었다. Drink - Category는 음료와 분류(대분류) 관계를 생각해 보았을 때 각종 커피 및 여러 음료는 음료라는 대분류에 속하기 때문에 1(Category):n(drink) 관계로(One-to-Many) 지정해 주었다. Category-DetailCategory 또한 1:n 관계로 묶어 주었다.

만약 그 참조를 반대로 생각한다면 Category 테이블에 해당 명칭이 중복해서 들어가게 되므로 Database의 유일성과 최소성에 위배된다. 이렇게 관계에 대해 정의를 해 줄때 각 DB테이블의 데이터의 주체성에 대해 고민해 보거나 데이터가 들어갔을 때를 생각해보면 쉽게 결정 내릴 수 있다.

Drink-Nutrition은 1:1 관계로 정의했다. 각 음료별로 영양정보가 각각 다를 수 밖에 없으므로 Drink(음료)로 부터 Nutrition으로 정방향 참조로 해두었다.

다대다(ManyToMany)관계도 구현해 두었는데 Drink-Allergic(알레르기) 관계를 생각해 보고, 실제 해당 홈페이지를 참조하면 여러 개의 음료와 여러 종류의 알레르기가 n:m 관계로 대응되는 것을 확인할 수 있다. 어느 한쪽으로 참조 방향을 주게 되면 유일성과 최소성에서 멀어지게 된다. 따라서 이때에 중간 테이블을 하나 두고 다대다 관계를 설정하면 비용도 줄어들고 관계가 간결해지고 명확해진다. Drink-Size의 관계도 ManyToMany 관계가 된다.

실제 위 모델을 바탕으로 SQL 및 ORM 테스트를 다음 포스트에서 진행해 보겠다.

profile
wanna be good developer

0개의 댓글