카테고리 없음

server - 4 (DATABASE 설계 & AWS RDS 설정)

팅탱팅탱 2024. 4. 14. 23:30

ERD는 프로젝트 시작과 동시에 설계하는 것이 좋습니다.

기획과 디자인이 어느정도 나와 개발자가 작업을 시작할 수 있는 시점을 말하는 것입니다.

 

ERD의 세세한 내용은 언제든지 바뀔 수 있기에 처음부터 완벽하게 만들 필요는 없습니다.

큰 틀을 정해두는 것이 1차 목표, 그 후 실제 기능 구현을 진행하며 필요한 내용을 수정합니다.

 

명심해야할것은

모든 팀원이 인지하는 데이터베이스는 동일해야 한다는 것입니다.

각자 자기 마음대로 DB를 설계하고, 작업 후 나중에 합치는 행위는 매우 좋지 않습니다.

처음에 빠르게 ERD를 설계하여, 모두가 공통된 데이터베이스에 대해 인지한 후 작업을 하는 것이 좋습니다.

 

DATABASE 설계

도서 대여 관리 앱에 대한 간단한 요구사항을 살펴보면

사용자 관련 요구 사항

  1. 카카오 소셜 로그인을 구현 할 예정이다.
  2. 회원 탈퇴 기능이 필요하다.
  3. 이름, 닉네임, 전화번호, 성별이 필요하다.

책 관련 요구 사항

  1. 사용자가 책 여러 권을 대여할 수 있다.
  2. 책은 하나의 카테고리가 있다.
  3. 책은 제목, 설명에 대한 정보가 필요하다.
  4. 책 소개 페이지에 해시태그가 붙을 수 있고, 책 한 권에 해시태그 여러 개가, 해시태그 하나가 여러 책에 붙을 수 있다.
  5. 사용자가 책 설명 페이지에서 책에 좋아요를 누를 수 있다.
  6. 카테고리 별로 현재 몇 개의 책이 있는지 집계가 필요하다.

알림 관련 요구 사항

  1. 알림은 공지 관련 알림, 책 반납 시간 임박 알림, 마케팅 알림이 있을 수 있다.

 

먼저 테이블 이름과 칼럼 이름은 모두 소문자, 그리고 단어 구분은 대소문자가 아닌, 밑줄로 구분해주는 것이 좋습니다.

기본 키를 위해 각 엔티티 정보 중 유일한 값을 기본 키로 설정하기 보다는 index를 따로 두는 것이 편합니다, 또한 각 index를 위한 id를 book_id, member_id 이렇게 보다는 그냥 id로 이름을 짓는 것이 좋습니다.

기본 키 타입은 int가 아닌 추후 서비스 확장을 고려하여 bigint로 하는 것이 좋습니다.

그러면 위 그림처럼 됩니다.

 

각각의 타입은 PM에게 물어봐서 확실하게 결정이 가능하게 하면 됩니다.(일단 위 사진은 임의로 타입을 저렇게 지정)

 

 

description의 경우 text타입은 string과 같이 길이 제한이 없는 타입인데 이것또한 pm과 상의를 통하여 글자수를 결정하는 것이 좋습니다.

gender의 경우 0이면 남자, 1이면 여자 이렇게 하는 경우도있고 varchar로 설정하여 문자로 두고 enum으로 관리를 해도 됩니다.

또한 아래처럼 create_at, update_at을 테이블마다 추가 해주는 것이 좋으며, datetime(6)는 밀리초 소수점 6자리까지 구분한다는 의미입니다.

왜 밀리초까지 구분할까요?

a: 나중 기능 구현을 염두한 설계입니다. 최신순 정렬 기능은 정말 흔한 기능입니다. 근데 초 단위까지만 저장을 하게 된다면 동시에 책을 등록하여 created_at이 초 단위까지 같은 상황이 일어나면 최신순 정렬이 잘 안되기에, 밀리초 까지 구분을 하는 것입니다.

(Mysql은 기준 6자리가 최대입니다.)

 

또한 멤버테이블은 status와 inactive_date를 두는 것이 좋습니다.

왜일까요? 

기능 구현시 회원 탈퇴, 게시글 삭제 등의 연산을 HTTP Method중 delete로 바로 삭제를 해버리는 방법도 있습니다(이를 Hard delete라고 합니다)

하지만 Hard delete의 방법은 지양하는 것이 좋습니다. 게시글은 요구 사항에 따라 다르겠지만, 유저의 경우 예시를 들어보자면 인스타그램같은 경우 , 회원 탈퇴를 철회하고 다시 돌아오는 회원들이 존재합니다.

그리고 아래와같은 요구사항이 있다고 해보면,

"매일 인기가 있는 사용자 상위 5명을 집계해서 보여줘야한다. 근데 이때 join 연산으로 가져와서 보여주도록 되어있는 상태"

이때 상위 1등이 갑자기 탈퇴를 하고 delete로 그 자리에서 삭제를 하게 된다면 갑자기 1등은 없고 2 3 4 5 등만 존재하게 되버리는 것입니다. (이부분도 요구 사항에 따라 다를 수 있습니다.)

 

따라서 사용자같이 곧바로 지워버리게되면 위험한 엔티티는 바로 delete를 하는 것이 아니라 

일단 비활성화 상태로 두고, 일정 기간동안 비활성인 경우 자동 삭제가 되도록 설계하는 것이 좋습니다.

 

이때 status를 active, inactive등 enum으로 관리하기 위해 varchar(15)로 둔것이고 경우에 따라 0이면 비활성화, 1이면 활성화 이런식으로 구현을 해도 됩니다. 그리고 얼마동안 비활성된 상태인지 알아내기 위해 inactive_date를 따로 뒀습니다.

 

그렇다면 어떻게 자동으로 지울까요?

batch란 정해진 시간에 자동으로 실행되는 프로세스입니다. 예시로 매일 새벽 2시에 자동으로 member테이블을 검사하여 inactive된 이후 7일이 지난 경우 삭제하도록 할 수 있습니다.

이를 soft delete라고 부릅니다.

꼭 회원 뿐만 아니라 요구사항에 휴지통 기능(삭제했다가 다시 복구가 필요한 기능)이 있는 경우도 바로 delete보다는 soft delete를 해야합니다. (soft delete는 HTTP Method중 patch입니다)

 

연관 관계에 대한 고민

Mysql은 RDB기반이고, RDB에서는 외래 키로 연관 관계를 표시합니다.

그렇다면 사용자가 책을 대여할때 연관 관계를 어떻게 해야할까요?

사용자랑 책이랑 1:N을 하면 될까요?

테이블을 보면 테이블에서 book이 의미하는 것은 책 종류를 말하는 것이지 실제 책 한권을 얘기하는건 아닙니다.

한 종류의 책을 여러 사용자가 대여하고, 한 사용자가 여러 종류의 책을 대여할 수 있으니 이때 사용자와 책은 N:M관계입니다.

 

이렇게 N:M 관계일때는 가운데에 매핑 테이블을 따로 둬야합니다.

가운데 매핑 테이블은 양쪽의 기본 키를 외래키로 가지고 각각 1:N 관계를 가집니다.

 

책과 책 카테고리의 경우 어떻게 매핑을 할까요?

현재 요구 사항을 보면 책에 카테고리 한 종류만 붙습니다. 카테고리 하나당 그저 여러 종류의 책이 관계를 가지기에, 카테고리와 책이 1:N 관계입니다.

그러나 책 한종류에 여러 카테고리가 붙을수있다면 N:M관계이므로 당연히 가운데 매핑 테이블을 둬야 합니다.

 

책에 붙는 해시태그, 사용자가 책에 누르는 좋아요는

해시태그도 여러개가 한 책에 붙고, 책에 여러 해시태그가 붙기에 N:M 관계 입니다.

마찬가지로 한 종류의 책에 사용자 여러명이 좋아요를 누르고, 한 사용자가 여러 책에 좋아요를 누르기에 이 또한 N:M 관계입니다.

 

따라서 위와 같이 다대다 매핑 같은 경우 가운데에 매핑 테이블을 두어서 설계가 가능합니다.

 

그렇다면 알림의 경우는 어떻게 설계할까요?

알림의 까다로운 점은 

"공지사항에 대한 알림은 알림 터치시 해당 공지사항으로 이동이 되고, 마케팅 알림의 경우 터치시 해당 마케팅으로 이동이된다"

라는 요구사항이 붙으면 좀 힘들게됩니다.

 

여기서 설계를 할때 어려운 부분이 어떤 것에 대한 알림인지 어떻게 알아내지? 라는 것입니다.

이에 대해서 3가지 설계 방법이 있습니다.

 

1. 슈퍼 타입과 서브 타입의 구성

이런 모양으로 설계할 수 있습니다.

 

2, 하나의 테이블에 두고 dtype으로 구분

간단하게 모든 내용을 다 한 테이블에 두고 dtype으로 구분을 하는 방법이 있습니다.

이때 dtype을 테이블로 따로 관리를 하거나 enum으로 관리하는 것은 선택하면 됩니다.

 

3. 테이블 다 나누기

 

 

데이터 베이스는 처음부터 완벽하게 설계할 수 없습니다. 그러나 경험이 쌓임에 따라 미래를 예측하여 이렇게 했다가 나중에 바꾸겠지? 하는 부분이 있습니다.

요구 사항중 사용자가 책에 좋아요를 누를 수 있고 이를 집계를 한다고 했는데 이럴때 책 테이블에 likes 칼럼을 두고 좋아요를 집계하는 것이 좋을까요? 좋아요를 누르면 +1 취소하면 -1 이렇게 하는것은 큰 무리는 없지만 

"사용자 간 차단 기능이 생기게 되어 차단 한 사용자가 누른 좋아요는 집계를 하지않는다"

라는 요구 사항이 생기게되는 경우들을 대비하여서 좋아요 개수를 집계하는 것은

순수 DML 연산으로, book_likes에서 해당 책 아이디를 가진 것이 몇개인지 직접 세는 것이 좋습니다.

 

 

RDS의 설정

데이터 베이스를 로컬 컴퓨터(서버 개발자가 작업하는 컴퓨터)에 두는 것이 좋을까요?

좋지 않습니다.

컴퓨터를 끄면 데이터 베이스 접속이 안되기도하고, 로컬 컴퓨터에 접속을 한다는 것은 해당 컴퓨터의 데이터베이스로 접속이 되도록 포트포워딩을 해야합니다.

따라서 데이터베이스도 EC2처럼 외부 컴퓨터를 빌려서 사용하는 것이 좋습니다.

EC2에 데이터 베이스를 설치해서 사용해도 좋으나, RDS를 사용하게 될 경우 더 유연하게 데이터 베이스를 사용할 수 있기에 RDS를 설정해서 사용해보는것도 좋습니다.