DB 네이밍 규칙
- 테이블명, 컬럼명은 소문자로 작성하고 snake_case를 사용한다.
-
테이블명은 복수형을 사용하자. (선택사항)
- 여러 개 데이터를 가지고 있음을 표현
- 회사마다 규칙이 갈리므로, 복수형이든 단수형이든 일관성 있게만 사용하면 됨
- 축약어를 사용하지 않는다.
- SQL문은 예약어만 대문자로 작성하자. (SELECT, FROM, WHERE…)
DB 설계 핵심 원칙
- 핵심 원칙: 중복 없애기 (정규화)
- 데이터 간 모순(이상 현상)의 근본적 원인은 데이터 중복이고, 정규화는 데이터 중복을 제거
- e.g. 두 테이블에 작성자 컬럼이 있는데, 모두 수정하다가 한 데이터를 빼먹으면 갱신 이상 발생
DB 설계 과정
-
저장해야 하는 데이터 파악하기
- 대략적인 UI 디자인 기획을 보고 필요한 데이터 파악
- 가끔 글로만 정리된 요구사항이 있을 수 있지만, 놓치는 부분이 생길 수 있어 좋지 않은 방식
- 기준: 나중에 조회해서 쓸 일이 있겠다 싶은 데이터를 전부 저장
- 대략적인 UI 디자인 기획을 보고 필요한 데이터 파악
-
그룹핑해서 분류하기
- 관련 있는 것들끼리 묶어 상위 개념을 찾음 (= 엔터티 = 테이블)
- 따로 법칙이 있다기보다 인간이 모두 가지고 있는 보편적인 분류 능력을 따르자
- e.g.
- 아이디, 패스워드, 이름, 이메일 → 사용자 (엔터티)
- 영화 이름, 영화에 출연한 배우, 영화 상영 시간 → 영화 (엔터티)
- 게시글 제목, 게시글 내용, 게시글 생성 시간 → 게시글 (엔터티)
-
6가지 규칙을 적용하며 테이블 분리해나가기
- 유의점
- 데이터 예시를 입력하며 파악하자
- 규칙 1 + 규칙 2의 결과는 규칙 3의 결과 동일 (무얼 선택해도 괜찮음!)
- 처음에 완벽한 설계가 안돼도 추후 데이터 중복을 발견해 수정 가능하니 불안해하지 말자
-
연관 관계 파악 관련 규칙
- 규칙 1: 한 칸에 한 가지 정보만 들어가야 한다 (제1정규형)
- 한 칸에 두 가지 정보가 있을 시, 테이블을 분리하고 FK를 적용
- FK 적용이 규칙 1을 어길 경우, 반대쪽 테이블에도 FK를 적용해보자
- ‘한 가지 정보’의 기준은 절대적이지 않아서, 자신의 서비스에 맞게 판단해야 함
- e.g. 손/흥민 or 손흥민, 01012341234 or 010/1234/1234
- 한 칸에 두 가지 정보가 있을 시, 테이블을 분리하고 FK를 적용
- 규칙 2: 어떤 테이블에 FK를 넣어도 ‘규칙 1’을 못 지킬 때는 중간 테이블을 하나 더 만들자
- 양쪽 테이블의 FK를 중간 테이블로 옮기기
- 중간 테이블의 이름은 동사를활용하면 좋음 (직관성, 가독성 상승)
- e.g.
-
students
&courses
- ->
course_registrations
{id(PK), student_id(FK), course_id(FK)}
- ->
-
movies
&actors
- ->
casting
{id(PK), movie_id(FK), actor_id(FK)}
- ->
-
- 규칙 3: 헷갈릴 땐 연관 관계를 파악해보자 (1:1, 1:N, N:M)
- 판단 방법
- 엔터티 간에 어울리는 동사를 찾기 (A가 B를 ___.)
- e.g.
- 사용자가 이메일을 소유한다.
- 이메일은 사용자에 의해 소유되어진다.
- e.g.
- 적절한 단어 찾기 (하나의 or 여러개의)
- e.g. ‘하나의’를 고정해서 따져보기
- 하나의 사용자는 ___ 이메일을 소유한다.
- 하나의 이메일은 ___ 사용자에 의해 소유되어진다.
- e.g. ‘하나의’를 고정해서 따져보기
- 관계 파악하기 (1:1, 1:N, N:M)
- e.g. 사용자와 이메일은 1: N 관계
- 엔터티 간에 어울리는 동사를 찾기 (A가 B를 ___.)
- 1:N 관계
- N 쪽 테이블에 FK 들어가야 함
- N:M 관계
- 중간 테이블이 있어야 하고, 중간 테이블에 두 테이블의 FK가 들어가야 함 (1:N으로 해소)
- 1:1 관계
- 아무 테이블에 FK를 넣어도 됨
-
합쳐도 되는지 고려해보자 (왠만하면 1:1 관계로 분리하지 않는 걸 추천)
- 통쨰로 조회하는 일이 많다면 합치는게 좋음
- 만약 각각 따로 조회할 일이 많다면 분리하는게 좋음
- 판단 방법
- 규칙 1: 한 칸에 한 가지 정보만 들어가야 한다 (제1정규형)
-
중복 없애기 관련 규칙
- 규칙 4: 데이터 중복이 발생하는 컬럼이 있는지 확인하자
-
임의의 데이터를 넣고 시뮬레이션해서 데이터 중복 발생 여부 파악
- e.g. 게시물 테이블의 작성자 데이터가 중복됨
- 중복이 있다면 테이블 분리하고 FK 적용
- 수정 포인트가 하나가 되므로, 갱신 이상 여지가 사라짐
-
임의의 데이터를 넣고 시뮬레이션해서 데이터 중복 발생 여부 파악
- 규칙 5: 가짜 중복과 진짜 중복 구별하기
- 실제 서비스에서 A 데이터 값을 수정하면, B 데이터 값도 같이 수정되어야 하는가?
- e.g. id 1 게시물의 작성자를 수정하면, id 2 게시물의 작성자도 수정해야 하나?
- 같이 수정되어야 하면 진짜 중복, 아니라면 가짜 중복
- 진짜 중복인 경우 테이블 분리해야 함
- 실제 서비스에서 A 데이터 값을 수정하면, B 데이터 값도 같이 수정되어야 하는가?
- 규칙 6: 숨어있는 중복을 찾아라
- 숨어 있는 중복
- 겉으로는 중복이 아닌 것 같지만, 무언가 수정해야할 때 같이 수정해야 하는 경우
- e.g.
users
&posts
->likes
(중간 테이블)- 좋아요를 제거할 때, 게시글의 좋아요 수도 같이 수정해야 함
- 주로 통계치(합계, 평균, 최대값 등)를 낼 때 발생
- 해결 방법: 테이블에서 통계치 칼럼을 없애야 함
- e.g. 좋아요 수 없애기
- 좋아요 수를 알고 싶다면, 좋아요 테이블에서 필터링하여 개수 카운팅하자
- e.g. 좋아요 수 없애기
- 숨어 있는 중복
- 규칙 4: 데이터 중복이 발생하는 컬럼이 있는지 확인하자
- 유의점
DB 설계 반영 지침
-
최대한 정규화를 지켜서 DB 설계하자
- 정규화 적용하지 않은 케이스의 의견들
- 정규화를 지키면 테이블 개수가 많아져서 관리가 불편해요.
- → 데이터 중복으로 인해 발생하는 단점들이 훨씬 크고 관리하기가 더 어렵다.
- JOIN을 많이 하면 할수록 성능이 안 좋아져서 정규화를 안 했어요.
- → 실제로 JOIN을 많이 했을 때 성능이 안 좋아지는 경우도 존재한다. 하지만 이렇게 얘기하는 사람치고 실제로 성능 측정해본 사람이 아무도 없다. (추측만 했을 뿐)
- 정규화를 지키면 테이블 개수가 많아져서 관리가 불편해요.
- 즉, 이상 현상 방지에 가장 초점을 두자
- 데이터 중복으로 인해 실수로 데이터가 잘못 관리되는 문제가 더 큼
- 성능 개선은 느려지기 전까지 최대한 안 건드리는 게 Best!
- 필요성을 느낀다면 반드시 ‘측정’을 기반으로 해야 함
- 역정규화는 정말 구조로 인한 성능 문제가 클 때만 사용하라
- 정규화 적용하지 않은 케이스의 의견들
-
ERD 표기 지침
- DB 설계 시 ERD 그리는 게 필수가 아니어서, 보고 해석하는 방법 정도만 알아도 충분
- 홀로할 때는 편하고 빠른 방법으로 진행 (엑셀, A4지…)
- 협업할 때는 툴 사용 (ERD Clould, dbdiagram…)
- 1:1 관계인지 1:N 관계인지만 파악할 수 있으면 됨 (그 외 표기는 잘 안쓰임)
-
데이터 타입 실전 활용 지침 (MySQL 기준)
- 주요 사용 타입
-
정수를 저장해야 하는 경우 :
INT
-
10억이 넘어가는 정수를 저장해야 될 수도 있는 경우 :
BIGINT
-
실수를 저장하고 싶은 경우 :
DECIMAL
-
문자를 저장해야 하는 경우 :
VARCHAR(글자수)
-
6만이 넘어가는 문자를 저장해야 하는 경우 :
LONGTEXT
-
TimeZone을 고려하지 않고 날짜/시간 데이터만 저장하면 되는 경우 :
DATETIME
- ex) 국내 서비스
-
TimeZone을 고려하면서 날짜/시간 데이터를 저장해야 하는 경우 :
TIMESTAMP
- ex) 글로벌 서비스
-
True, False의 형태를 저장하고 싶은 경우 :
TINYINT(1)
-
정수를 저장해야 하는 경우 :
- 참고: 숫자는 숫자로 저장할 수도 있고 문자로 저장할 수도 있음
- DB 관점에서는 “계산에서 쓰는 값인지 안 쓰는 값인지”를 기준으로 선택
- 휴대폰 번호는 문자로 저장 (숫자를 더해서 사용하지 않고 단순히 고유의 값으로 사용할 뿐)
- 주민등록번호도 마찬가지로 문자로 저장
- 주요 사용 타입
현업에서 잘 사용하지 않는 데이터 타입 :
CHAR
,FLOAT
,DOUBLE
,TEXT
등