ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데이터베이스 정규화 (database normalization)
    데이터베이스 2022. 3. 29. 20:25

    이전에 SQL과 NOSQL 특징 및 장단점에 대해 쓰면서 DB의 존재 의의에 대해 쓴 적이 있습니다.

     

    데이터들의 중복을 없애고 자료를 구조화하여 효율적으로 데이터를 관리하기 위해서이다.

     

    DB 정규화를 알아야 하는 이유와 같다고 생각합니다.

     

    과제를 진행하면서 ERD를 진행하면서 데이터베이스에 대한 고민도 많아지고

    어떤 기준으로 나눠야 하는 건지 고민하다가 전에 백엔드 엔지니어면 데이터베이스 정규화도 알아야 된다고 들었던 기억이 나서 이렇게 찾아봤습니다.

     

    일반적으로 3NF까지 알면 DB 정규화 작업을 문제 없이 할 수 있다고 하니 우선 3NF까지 학습하고자 합니다.

     

    순서는 아래와 같이 차례대로 정규화 하시면 됩니다. (각각의 정규화는 이전 단계의 정규화를 완료했다고 가정)

    1NF => 2NF => 3NF

     

    1NF (First Normal Form) : 테이블 분할 & 기본키 지정

    Atomic columns : 컬럼의 값이 원자성을 가져야 한다.

    쉽게 얘기해서 하나의 컬럼(속성)에 두 개 이상의 값을 넣지 말라는 이야기다.

     

    그리고 반복 그룹도 안 된다.

    예를 들면 컬럼명이 언어1, 언어2 이런 식으로 언어가 추가될 때마다 테이블 구조를 변경해야 하면 안 되기 때문이다.

     

    1NF만 고려할 때의 적용 전 예시와 적용 후의 예시

    < 정규화 이전 예시 >

    유저 아이디 이름 언어
    bruno 강민중 Python, JavaScript
    amy 에이미 JavaScript, Java
    joel 죠엘 C

     

    < 제 1 정규화 적용 예시 >

    < 유저 정보 >

    유저 아이디 이름
    bruno 강민중
    amy 에이미
    joel 죠엘

    < 유저별 언어 >

    유저 아이디 (FK) 언어
    bruno Python
    bruno JavaScript
    amy JavaScript
    amy Java
    joel C

     

    FK로 연결했으므로 유저 정보를 변경해야 할 경우 "유저 정보" 테이블에서만 정보를 변경하면 되고

    기존의 어트리뷰트 하나에 2가지 값이 들어가 있던 문제도 해결했습니다.

     

    < 정리 >

    컬럼의 값이 원자성을 가지지 못 하면 JOIN이 어렵거나 불가능 할 수 있다.

    그리고 컬럼의 값이 원자성을 가진다고 해도 컬럼을 추가하는 것처럼 테이블 구조를 변경해야 하는 것은 좋지 않다.

     

    프로젝트를 한 번 이상 해 보신 분들이라면 공감하실겁니다.

    프로젝트 중간에 스키마 즉 테이블 구조를 변경하는 것이 얼마나 어려운 것인지를 아실겁니다.

     

    데이터베이스를 정규화 하는 이유와 RDB를 사용하는 이유가 일맥상통한다고 생각하는데

    그 이유가 바로 "데이터의 중복을 막고 이를 통해 데이터가 꼬이는 것을 막기 위해서" 입니다. 

     

    데이터 완전성을 유지하면서 정보 저장을 빠르고 효율적으로 하기 위해서 RDB를 사용하는데

    1NF를 지키지 않는다면 그 의미가 없다고 보기에 이를 잘 지켜야 합니다.

     

    2NF (Second Normal Form)

     

    No partial dependencies : 부분 함수 종속성을 제거 (중복키가 없어야 한다.)

    부분 종속성 문제가 해결되지 않으면 데이터의 정합성 보장할 수 없다.

    즉, 목적에 맞게 분리해라!

    < 나쁜 예시 >

    이 예시는 3NF의 예시에도 속하는 것 같아서 걱정이 되지만.. 부분 함수 종속성을 보여드리고자 준비한 예시이기에 이 부분에 초점을 맞춰주시면 감사하겠습니다..!

    유저 아이디 이름 나이 언어 성적
    bruno 강민주 25 Python A
    bruno 강민주 25 JavaScript B+
    kyle 홍진우 21 NodeJS A+
    kyle 홍진우 21 JavaScript B
    amy 에이미 29 Java C

     

    X와 Y가 있을 때 X를 결정자, Y를 종속자라고 하면

    Y는 X에 종속된다 라고 표현한다.

    그리고 이 결정자가 하나만 있는 테이블을 완전 함수적 종속성을 가지고 있다고 얘기한다.

     

    위처럼 작성하는 것이 왜 나쁜 것인지 생각해보자. (기본키는 유저 아이디와 언어로 가정한다.)

    1. 유저 정보 변경해야 할 경우 중복 데이터들 수정하는 과정에 놓치거나 실수하는게 있으면 갱신이상 발생할 수 있다.

    2. 새로운 유저를 등록하는데 아직 배운 언어가 없을 경우 NULL로 처리해야 하는데 기본키의 컬럼이므로 해당 유저를 등록할 수 없다. 이런 경우를 삽입이상 이라고 한다.

    3. Java 를 삭제할 경우 Java뿐만 아니라 해당 유저인 amy 에 대한 정보도 삭제 되는 경우를 삭제이상 이라고 한다.

     

    < 제2 정규화 적용 예시 >

    < 유저 정보 >

    유저 아이디 이름 나이
    bruno 강민주 25
    kyle 홍진우 21
    amy 에이미 29

     

    < 언어별 성적 >

    유저 아이디 (FK) 언어 성적
    bruno Python A
    bruno JavaScript B+
    kyle JavaScript A+
    kyle NodeJS B
    amy Java C

    참고 : FK의 중복은 중복으로 치지 않는다.

     

     

    3NF (Third Normal Form)

    No transitive dependencies : 이행적 함수 종속성 제거

    즉, 기본 키가 아닌 속성들은 기본 키에만 의존해야 함을 의미한다.

     

    이행적 함수 종속 설명

    A(PK) B C D E F 컬럼이 있다면

    A 컬럼을 통해 B C 알 수 있고 (A -> B C)

    C 컬럼을 통해 D E F 알 수 있다면 (C -> D E F)

    A -> D E F 이렇게 성립되는 것을 이행적 함수 종속이라고 한다.

     

    그래서 이런 경우 A B C(FK) 와 C D E F 두 테이블로 나눠야 한다.

     

     

    < 요약 및 정리 >

    제1 정규화

    모든 속성은 반드시 하나의 값만 가져야 한다.

    컬럼을 추가하는 것처럼 테이블 구조를 변경해서는 안 된다.

     

    제2 정규화

    중복키를 제거하여 목적에 맞게 테이블을 나누자. (기본키 일부에만 종속되지 않도록 해야 한다.)

     

    제3 정규화

    이행적 함수 종속을 제거하자.

     

     

    현업에서 2NF와 3NF를 굳이 나눌 필요가 있을까 하는 생각도 든다.

    결국 이렇게 정규화를 하는 이유가 중복되지 않도록 데이터들을 그룹화해서 최대한 잘게 나눠야하기 때문이다.

     

     

    < 참고 자료 >

    https://jhnyang.tistory.com/360?category=817647

    https://www.youtube.com/watch?v=FYDHJbIwm5Y&t=7s

    https://www.youtube.com/watch?v=pMcv0Zhh3J0

     

    '데이터베이스' 카테고리의 다른 글

    SQL과 NOSQL 특징 및 장단점  (0) 2022.03.25
    트랜잭션  (0) 2022.03.14

    댓글

Designed by Tistory.