코드스테이츠 11주차 / Instagram 스키마 디자인

support·2022년 1월 22일
1
post-thumbnail

인스타그램의 모든 기능과 프로토타입은 완성되어 있고
백엔드 개발자로서 데이터베이스의 스키마를 디자인해야 한다면, 어떻게 스키마 디자인을 해야 할까

스키마란?
1. 스키마는 데이터베이스의 구조와 제약 조건에 관한 전반적인 명세를 기술한 메타데이터의 집합이다.
2. 스키마는 데이터베이스를 구성하는 데이터 개체(Entity), 속성(Attribute), 관계(Relationship) 및 데이터 조작 시 데이터 값들이 갖는 제약 조건 등에 관해 전반적으로 정의한다.
3. 스키마는 사용자의 관점에 따라 외부 스키마, 개념 스키마, 내부 스키마로 나눠진다.

✅ 관계형 데이터베이스의 관계

관계형 데이터 베이스는 데이터끼리 관계를 맺을 수 있기 때문에 관계형이라는 이름이 붙었다
이 관계는 두 데이터가 서로 관련이 있을 때 맺을 수 있고 3가지 관계가 존재한다

일대일 (1:1) : 어느쪽에서 보더라도 하나의 관계만 가진다
일대다 (1:n) : 한쪽이 여러개를 가질 수 있다 (부모 자식 관계)
부모는 자식을 여러명 가질 수 있고 자식은 부모를 하나만 가질 수 있다
다대다 (n:m) : 양쪽 모두 여러개를 가질 수 있다

✅ 대표키 pk(Primary key) 외래키 fk(foreign key)

pk와 fk는 테이블의 필수요소이고 모든 테이블을 둘 중 하나 이상을 반드시 포함 하고 있어야 한다

Primary key

pk는 각 행을 고유하게 식별하는 역할을 가지고 테이블당 하나만 정의 할 수 있다
고유 인덱스가 자동으로 생성된다
ex) 한국 국민을 식별할 수 있는 대표키로는 주민번호가 존재한다

foreign key

외부 식별자키 이고 테이블 간의 관계를 의미한다
두테이블간의 부모,자식 관계 -> 종속이 필요한 관계일때 fk로 지정해 서로 참조할 수 있게 해준다
fk가 정의된 테이블이 자식테이블이다
참조되는 테이블을 부모 테이블이라 하고 부모테이블의 참조되는 컬럼에 존재하는 값만 입력 할 수 있다
부모테이블에 pk를 먼저 만들어야 fk를 만들 수 있다

테이블간의 관계를 맺을 때 대표키를 이용하여 관계를 맺는다
인스타의 포스트와 댓글의 관계로 예를 들면
댓글테이블의 칼럼에는 아래와 같이 데이터가 존재할 수 있다
id (pk) - 댓글아이디
userid - 작성자아이디
comment - 댓글내용
created_at - 작성날짜

여기서 이 댓글이 어떤 포스트안에 작성되었는지의 정보가 필요하다
id(fk) - 포스트아이디
이것을 외래키라고 한다

이때 포스트 아이디는 포스트테이블의 대표키이고
이 대표키를 댓글테이블의 외래키로 설정해서 관계를 맺을 수 있다

스키마 구현 방법

스키마 디자인을 할 때는 구현하려는 기능에 맞춰서 크게 나눠보고
그곳에 어떤 속성이 필요한지 생각을 해보며 구현 할 수 있다

인스타그램의 기능을 크게 세가지로 나눠보자
1. 인스타를 사용하는 유저 - 그 유저는 다른 유저를 팔로우하고 다른유저의 피드를 받아볼 수 있다
2. Post 를 올릴 수 있고 - Post안에 hashtag를 작성해서 많은 유저가 보게끔 할 수 있다
3. 올려진 게시물에 좋아요를 누르거나 댓글을 달아서 유저간의 소통을 할 수 있다

스키마 디자인

먼저 그들의 관계를 생각한 뒤 작성해보자

유저와 팔로워의 관계

user : follow = n:m

유저는 여러명을 팔로우 할 수 있다
유저가 팔로우한 사람 또한 여러명을 팔로우 할 수 있다

먼저 유저테이블을 만들고 유저테이블을 식별할 수 있는 고유키를 id로 만들어 준다
팔로잉 관계를 저장 할 수 있는 테이블도 만들어 준다


유저 - 팔로우팔로잉 - 유저 형식의 조인테이블

follow_id에 내가 팔로우하는 사람을 저장
following_id에 나를 팔로잉을 하고 있는 사람 저장
둘의 주체가 전부 다 유저이고 그 정보는 전부 유저테이블에 있다
유저테이블에 있는 pk를 각각의 fk로 넣어주면 된다

포스트와 해시태그의 관계

Post : Hashtag = n : m

하나의 포스트에는 여러개의 해시태그가 달릴 수 있다
하나의 해시태그에는 여러개의 포스트가 존재할 수 있다

다대다 관계를 작성하기 위해서는 join 테이블이 필요하다
post의 id와 hashtag의 id를 fk로 참조하고 있다

✅ join 테이블이 필요한 이유

join 테이블이 없이 하나의 테이블로 post가 존재하고 그안에 hashtag가 필드로 존재하게 된다면 안에 여러개의 해시태그가 배열형식으로 존재하게 되고 하나의 해시태그를 찾기 위해서는 모든 해시태그를 전부 돌아서 찾아야 한다

데이터를 나눠서 관계를 설정하고 fk로 해시태그를 찾아내면 원하는 해시태그만 찾을 수 있으므로 join 테이블이 필요하다
--> 데이터 구현방식이 비효율적이라 생각해서 나온게 NoSQL이다

포스트와 좋아요 , 포스트와 댓글의 관계

Post : Like = 1 : n
Post : Comment = 1 : n

한 포스트에는 여러개의 좋아요가 있을 수 있다
하나의 좋아요는 한 포스트에만 누를 수 있다

한 포스트에는 여러개의 댓글이 달릴 수 있다
하나의 댓글은 하나의 포스트에만 달 수 있다

포스트 테이블과 post_comment, post_like는 일대다의 관계이기 때문에 포스트 테이블 안에 두 테이블의 정보가 필요 없고
필요할 때 해당 포스트의 정보를 참조하면 된다

post_comment 와 post_like 의 user_id 는 post의 user_id와 다르게 댓글을 남긴 사람의 아이디 좋아요를 누른 사람의 아이디이다

유저와 포스트의 관계
user : post = 1 : N
한명의 유저는 여러개의 post를 작성 할 수 있다
하나의 포스트는 하나의 유저만 작성할 수 있다.

큰 틀을 설정해준 뒤 나머지 생각해야 되는 관계를 생각해서 연결해 주면 된다

Table users {
  id int [pk, increment] // auto-increment
  userId varchar
  password varchar
}

Table follow_following {
  id int [pk, increment] // auto-increment
  follow_id int
  following_id int
}

Table post {
  id int [pk, increment] // auto-increment
  img blob
  content varchar
  created_at timestamp
  total_like int
  total_comment int
  user_id int
}

Table hashtag {
  id int [pk, increment] // auto-increment
  name char
}

Table post_hashtag {
  id int [pk, increment] // auto-increment
  hashtag_id int
  post_id int
}

Table post_comment {
  id int [pk, increment] // auto-increment
  comment varchar
  created_at timestamp
  user_id int
  post_id int
}

Table post_like {
  id int [pk, increment] // auto-increment
  created_at timestamp
  user_id int
  post_id int
}


Ref: "users"."id" < "follow_following"."follow_id"

Ref: "users"."id" < "follow_following"."following_id"

Ref: "post"."id" < "post_hashtag"."post_id"

Ref: "hashtag"."id" < "post_hashtag"."hashtag_id"

Ref: "post"."id" < "post_comment"."post_id"

Ref: "post"."id" < "post_like"."post_id"

Ref: "users"."id" < "post"."user_id"

Ref: "users"."id" < "post_comment"."user_id"

Ref: "users"."id" < "post_like"."user_id"

참고
dbdiagram

0개의 댓글