ERD
Entity Relationship Diagram
고연차, 숙련개발자인지 판단하는 척도
하지만 일단 ERD를 잘 그려서 프로젝트를 어필하는 자리에 넣으면 좋은 무기가 될 수 있다. 그리고 언젠가는 해야하니 배우는 게 이득이다.
0. 잘 작성하는 법
- 연습 많이 하기
- 추상화,논리,비식별관계 등의 단어에 겁먹지 말라: 이론과 실제는 다르다.
- 자신이 관심있는 서비스나 영역의 ERD를 그려보면서 연습
1. PK/FK
프라이머리-키는 중복된 값을 가지지 않는다.(unique) 따라서 한 레코드를 대표하여 식별할 수 있는 값을 가진 필드이다.
대개 정수형태며, 번호 혹은 유일한 값을 지정함.
외래키는 다른 테이블의 PK를 참조하는 필드이다. 즉 타 테이블의 PK 데이터를 확보한다.
PK/FK를 활용하지 않으면 불필요하거나 중복된 데이터를 보유하게 되고 테이블읠 칼럼(필드)가 계속 증가하게 된다.
ex) 아티클 마다 유저 데이터 따로 적어주기
2. 일대일 vs 일대다 vs 다대다
1. 일대일 관계
- 어느 데이터에 종속되는 데이터가 하나만 있을 때 사용
- 예시: 사용자와 프로필의 관계
- 장고에서는 OnetoOneField()
- 그러나 보통 ForeignKey with unique=True로 구현하며 현재 장고에서는 이렇게 작성하는 것을 추천
2. 일대다 관계
- 어느 데이터에 종속되는 데이터가 여러개 있을 때 사용
- 예시: 사람과 은행계좌의 관계(나는 여러개의 계좌를 가질 수 있지만 계좌는 여러 주인을 가질 수 없다.)
- 장고에서는 ForiegnKey()
3. 다대다 관계
- 어느데이터에 종속되는 데이터가 여러개 있고 다른 데이터에도 종속될 수 있음.
- 예시: 회사원과 회의 세션의 관계.
- 일대다 관계로 양쪽이 연결된 중간 테이블(양쪽의 PK만 필드로 가짐)로 구현
- Django에서는 ManyToManyField 지원한다. 자동으로 중간 테이블을 생성해주는데, 개발을 하다보면 다른 데이터들을 넣어 다양한 역할을 수행할 수 있게 만들어야하는 경우 한계가 존재하며, 숨겨진 테이블로 인해 쿼리가 의도와 다르게 동작할 수 있다. 따라서 수동으로 중간테이블을 만들어주고 forienkey를 이용해 구현한다.
3. 식별/비식별관계
식별관계는 외래키가 PK역할도 같이 해주는 경우를 말한다. 비식별관계는 외래키가 PK 역할을 하지 않는다.
# 식별관계, onetoone
class Grade(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, primary_key=True, unique=True)# null=False(기본)
grade = models.IntegerField()
식별 관계는 반드시 외래키의 데이터에 종속되어야 한다 (예시: 군인은 반드시 소속이 있다)
class Soldier(models.Model):
name = models.CharField(max_length=50)
department = models.ForeignKey(Department, on_delete=models.CASCADE)
# Department(부모)의 데이터가 먼저 만들어져야 한다.
비식별 관계는 반드시 종속될 필요가 없다.(예시: 회사원은 소속 부서가 없을 수 있다.)
class Employee(models.Model):
name = models.CharField(max_length=100)
department = models.ForeignKey(Department, on_delete=models.SETNULL, null=True)
# Department의 데이터를 반드시 필요로 하지 않음
구상할 때 이렇게 누락되어도 되는지, 누락된 값이 존재할 때 어떻게 처리를 할것인지 미리 고민해보아야 한다.
둘중 선택하기
- 두 데이터간의 종속성이 강할 경우엔 식별관계로 지정하는 것이 편하다.
- 하나의 데이터를 날려버려도 다른데이터가 의미를 잃지않고 재사용가능하면 비식별 관계로 지정하는 것이 편하다.현업에서는...대부분의 관계는 비식별 관계로 처리하게 되는 경향이 있다. (데이터 정합성, 구현/운영의 용이성) - 다시 확인해볼것 -
Q:그러면 비식별관계에서 on_delete=CASCADE 옵션을 안 적용해줘도 괜찮지 않을까요?
A:네. on_delete 옵션의 다양성도 참고해보세요.
models.CASCADE(기본), models.SET_NULL, models.PROTECT 등
비식별관계에서의 조인연산(select_related)
class User(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
class Post(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
위와 같이 일대다 관계를 가진 두 모델이 있다.
posts = Post.objects.all()
for post in posts:
print(post.title, post.author.name, post.author.email)
데이터베이스에서 위와같이 데이터를 조회하려고 할때, post가 총 N개라면 총 몇번의 쿼리가 발생하는가? 언뜻보면 1번으로 보이지만 사실은 N*2+1번 발생한다. 외래키는 어디까지나 PK만 가져올 뿐이고, 실제로는 반복문 안에서 외래키의 데이터를 가져오기위해 또다시 DB에 쿼리를 보낸다.
posts = Post.objects.select_related('author').all()
for post in posts:
print(post.title, post.author.name, post.author.email)
이렇게 select_related를 사용하여 테이블을 조인하면, 한번의 쿼리만 날려도 된다!
연습
컨벤션 주의사항: 테이블명은 항상 복수형으로 해준다.
스벅 메뉴판 보면서 구상하기
- 카테고리
- 상세분류 - 신규출시, 시즌한정, 지역한정
- 음료의 이미지들
- 음료 설명, 영양정보
- 음료-이미지: 일대다
- 메뉴-카테고리-음료: 다대다(일대다대일)
- 알러지-음료/알러지테이블-음료: 다대다(일대다대일)
- 영양정보-음료: 일대일(unique=True)
구상할 때 유심히 볼 부분
- 일대일/일대다/다대다 관계 찾기
- 자료형(Data Type), Nullable 확인
- 테이블 공통 field 확인 (예: created_at, updated_at) 클래스 상속이용해 중복 줄일 수 있다.
- 추가로 분리 가능한 데이터 찾기: 예시 - 제주한정, 시즌한정 여부(추후 필드 자체가 의미없어질 수 있음) => 특성테이블 따로 개설해 정합성 확보 가능
새마을식당 보면서 구상하기
- DB가 필요한 것과 아닌것 구분
- 없어질 수도 있는것은 데이터로 관리
- 카테고리 테이블
- 음식 테이블-pk,이미지,이름,설명,카테고리
- 매장테이블-명칭, 위치, 상세주소,전화번호, 영업시간,휴일,주차,좌석,이미지
Q&A
- 장고에서 모델을 시각화하는 라이브러리 존재하므로 이용하면 좋다.(추후공유)
- ERD를 잘 읽는 법: 모든 서비스에서 코어가 되는 테이블들이 반드시 존재한다. 보통 이러한 테이블을 중점으로 확장하는 식으로 개발이 이루어지니 읽을 때도 비슷한 순서로 관계를 보면 된다.
- 레코드가 너무 많을 때 테이블을 분리하는 하는 경우는 별로 없다. 조회시 어느 테이블을 봐야할지 옵션을 정해야하기 때문.
- 같은 테이블에서 다대다관계인 경우: pk만 있는 테이블에 두번 일대다로 표현하면 될것 같다.
'웹개발' 카테고리의 다른 글
Django QnA-50 07.31 (0) | 2023.07.31 |
---|---|
DRF + ML 1일차 (0) | 2023.05.31 |
장고와 MVT(23.04.25) (0) | 2023.04.25 |
세션인증과 토큰인증 (0) | 2023.04.24 |
DRF 1강 - HTTP와 웹 동작 방식 (0) | 2023.04.18 |