Home > Computer Science > DB > DB 설계 규칙 정리

DB 설계 규칙 정리
DB

DB 네이밍 규칙

  • 테이블명, 컬럼명소문자로 작성하고 snake_case를 사용한다.
  • 테이블명복수형을 사용하자. (선택사항)
    • 여러 개 데이터를 가지고 있음을 표현
    • 회사마다 규칙이 갈리므로, 복수형이든 단수형이든 일관성 있게만 사용하면 됨
  • 축약어를 사용하지 않는다.
  • SQL문은 예약어만 대문자로 작성하자. (SELECT, FROM, WHERE…)

DB 설계 핵심 원칙

  • 핵심 원칙: 중복 없애기 (정규화)
    • 데이터 간 모순(이상 현상)의 근본적 원인데이터 중복이고, 정규화는 데이터 중복을 제거
    • e.g. 두 테이블에 작성자 컬럼이 있는데, 모두 수정하다가 한 데이터를 빼먹으면 갱신 이상 발생

DB 설계 과정

  • 저장해야 하는 데이터 파악하기
    • 대략적인 UI 디자인 기획을 보고 필요한 데이터 파악
      • 가끔 글로만 정리된 요구사항이 있을 수 있지만, 놓치는 부분이 생길 수 있어 좋지 않은 방식
    • 기준: 나중에 조회해서 쓸 일이 있겠다 싶은 데이터를 전부 저장
  • 그룹핑해서 분류하기
    • 관련 있는 것들끼리 묶어 상위 개념을 찾음 (= 엔터티 = 테이블)
    • 따로 법칙이 있다기보다 인간이 모두 가지고 있는 보편적인 분류 능력을 따르자
    • e.g.
      • 아이디, 패스워드, 이름, 이메일 → 사용자 (엔터티)
      • 영화 이름, 영화에 출연한 배우, 영화 상영 시간 → 영화 (엔터티)
      • 게시글 제목, 게시글 내용, 게시글 생성 시간 → 게시글 (엔터티)
  • 6가지 규칙을 적용하며 테이블 분리해나가기
    • 유의점
      • 데이터 예시를 입력하며 파악하자
      • 규칙 1 + 규칙 2의 결과규칙 3의 결과 동일 (무얼 선택해도 괜찮음!)
      • 처음에 완벽한 설계가 안돼도 추후 데이터 중복을 발견해 수정 가능하니 불안해하지 말자
    • 연관 관계 파악 관련 규칙
      • 규칙 1: 한 칸에 한 가지 정보만 들어가야 한다 (제1정규형)
        • 한 칸에 두 가지 정보가 있을 시, 테이블을 분리하고 FK를 적용
          • FK 적용이 규칙 1을 어길 경우, 반대쪽 테이블에도 FK를 적용해보자
        • 한 가지 정보’의 기준은 절대적이지 않아서, 자신의 서비스에 맞게 판단해야 함
          • e.g. 손/흥민 or 손흥민, 01012341234 or 010/1234/1234
      • 규칙 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.
              • 사용자가 이메일을 소유한다.
              • 이메일은 사용자에 의해 소유되어진다.
          • 적절한 단어 찾기 (하나의 or 여러개의)
            • e.g. ‘하나의’를 고정해서 따져보기
              • 하나의 사용자는 ___ 이메일을 소유한다.
              • 하나의 이메일은 ___ 사용자에 의해 소유되어진다.
          • 관계 파악하기 (1:1, 1:N, N:M)
            • e.g. 사용자와 이메일은 1: N 관계
        • 1:N 관계
          • N 쪽 테이블FK 들어가야 함
        • N:M 관계
          • 중간 테이블이 있어야 하고, 중간 테이블에 두 테이블의 FK가 들어가야 함 (1:N으로 해소)
        • 1:1 관계
          • 아무 테이블FK를 넣어도 됨
          • 합쳐도 되는지 고려해보자 (왠만하면 1:1 관계로 분리하지 않는 걸 추천)
            • 통쨰로 조회하는 일이 많다면 합치는게 좋음
            • 만약 각각 따로 조회할 일이 많다면 분리하는게 좋음
    • 중복 없애기 관련 규칙
      • 규칙 4: 데이터 중복이 발생하는 컬럼이 있는지 확인하자
        • 임의의 데이터를 넣고 시뮬레이션해서 데이터 중복 발생 여부 파악
          • e.g. 게시물 테이블의 작성자 데이터가 중복됨
        • 중복이 있다면 테이블 분리하고 FK 적용
          • 수정 포인트가 하나가 되므로, 갱신 이상 여지가 사라짐
      • 규칙 5: 가짜 중복진짜 중복 구별하기
        • 실제 서비스에서 A 데이터 값을 수정하면, B 데이터 값도 같이 수정되어야 하는가?
          • e.g. id 1 게시물의 작성자를 수정하면, id 2 게시물의 작성자도 수정해야 하나?
        • 같이 수정되어야 하면 진짜 중복, 아니라면 가짜 중복
        • 진짜 중복인 경우 테이블 분리해야 함
      • 규칙 6: 숨어있는 중복을 찾아라
        • 숨어 있는 중복
          • 겉으로는 중복이 아닌 것 같지만, 무언가 수정해야할 때 같이 수정해야 하는 경우
          • e.g. users & posts -> likes (중간 테이블)
            • 좋아요를 제거할 때, 게시글의 좋아요 수도 같이 수정해야 함
          • 주로 통계치(합계, 평균, 최대값 등)를 낼 때 발생
        • 해결 방법: 테이블에서 통계치 칼럼을 없애야 함
          • e.g. 좋아요 수 없애기
            • 좋아요 수를 알고 싶다면, 좋아요 테이블에서 필터링하여 개수 카운팅하자

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


Reference