1. 정규화 ( Normalization )

관계형 모델에서는 정규화 이론이라는 DB 설계 이론이 있습니다.

정규화 이론은 RDB를 효율적으로 잘 다루는데 있어 필요한 과정이며, 관계형 모델을 전제로 구축된 DB 설계 이론입니다.

정규화의 가장 큰 이점은 모순을 방지할 수 있다는 것입니다.
모순이란 논리적으로 불일치한 데이터가 발생하는 상황을 말하며, 모순이 발생한 상태를 변칙( Anomalies )이라고 합니다.

예를 들어, 다음과 같은 릴레이션을 가정해보겠습니다.

victolee는 1학년일까요 3학년일까요?
릴레이션은 참인 명제의 집합이므로, 두 데이터 모두 사실입니다.
즉, victolee가 1학년인지 3학년인지 명확히 알 수가 없는데, 이러한 상황을 변칙이 발생했다고 합니다.

모순이 생기는 이유는 데이터의 중복이 가장 큰 역할을 하는데, 정규화를 통해 중복을 제거함으로써 모순을 해결할 수 있습니다.
즉, 정규화는 릴레이션 내에서 중복을 제거하는 과정이라고 할 수 있습니다.

정규화 과정, 즉 중복 제거를 통해 얻을 수 이점은 다음과 같습니다.
  • 응용프로그램 단에서 불필요한 로직을 없앨 수 있다.
  • 올바른 데이터만 얻을 수 있다. ( 변칙 방지 )
  • 불필요한 쿼리( 예를 들면, 서브쿼리 ) 제거로 성능 향상




2. 정규형 ( Normal Form, NF )
정규화 과정은 각각의 정규형이 되기 위한 조건들을 충족시키는 과정이라고 볼 수 있습니다.
정규형에는 단계가 있는데, 높은 단계로 갈수록 중복이 적은 릴레이션으로 설계됩니다.
  • 제1 정규형 (1NF)
  • 제2 정규형 (2NF)
  • 제3 정규형 (3NF)
  • 보이스코드 정규형 (BCNF)
  • 제4 정규형 (4NF)
  • 제5 정규형 (5NF)
  • 제6 정규형 (6NF)

다음은 정규형의 대략적인 개요, 특징들을 말씀드리려 합니다.
  • 높은 단계의 정규형은 그 이전 정규형들이 갖는 조건들을 만족해야 합니다.
    • 예를 들어, 4NF는 1NF~BCNF까지의 정규형 조건들을 기본적으로 만족해야 합니다.
  • 핵심 정규형은 BCNF, 5NF이며, 그 외의 정규형을 목표로 하지 않습니다.
    • 일반적으로 BCNF를 만족하면 5NF를 만족하는 경우가 많기 때문에 BCNF를 목표로 두기도 합니다.
  • 특히 6NF는 직교성을 다룰 때 유용하지만, 릴레이션이 너무 많아져 불필요한 join이 많아지므로 6NF를 목표로 두진 않습니다.
  • 2NF ~ BCNF는 함수 종속성의 제거를 통해 만족하게 되며, 4NF ~ 6NF는 결합 종속성의 제거를 통해 이뤄집니다.




3. 용어 정리

각 정규형이 어떤 조건들을 만족해야 하고, 이를 해결하는 과정을 살펴보기 전에 용어를 먼저 정리하면 좋을 것 같습니다.

  1. 슈퍼키
    • 릴레이션에서 특정 튜플을 유일하게 구분할 수 있는 애트리뷰트의 조합을 가진 키
    • 튜플을 유일하게 구분할 수 있으면 되기 때문에, 슈퍼키는 여러개 존재할 수 있습니다.
    • 예를 들어, A, B, C 애트리뷰트가 있을 때 (A,B), (B,C) 조합만으로 튜플을 구분 할 수 있다면, 해당 조합이 슈퍼키가 됩니다.
  2. 후보키
    • 슈퍼키 중에서 최소한의 애트리뷰트 조합으로 특정 튜플을 유일하게 구분 할 수 있는 키
    • 예를 들어, (A,B), (B,C) 슈퍼키가 존재할 때 B 애트리뷰트만으로도 튜플을 구분할 수 있다면, B는후보키입니다.
      • 즉, 슈퍼키보다 작은 범위라고 할 수 있습니다.
  3. 진부분집합
    • 관계형 모델은 수학의 집합론에 근거한 모델이기 때문에 집합에 대한 개념이 필요합니다.
    • 진부분집합은 자신을 제외한 부분집합을 의미합니다.
    • 예를 들어, {1,2} 집합의 부분집합은 {공집합, {1}, {2}, {1,2}}이며, 진부분집합은 {공집합}, {1}, {2}가 됩니다.
  4. 무손실 분해 ( Lossless Decomposition )
    • 정규화를 진행하는 과정에서 중복을 제거하는 방법으로 릴레이션을 분해합니다. 이 때 원래의 정보를 잃어버리지 않으면서 분해하는 것을 무손실 분해라고 합니다.
    • 즉, 릴레이션을 분해할 때 무손실 분해가 되어야 합니다.
    • 무손실 분해가 되면 분해된 릴레이션을 join 해서 원래의 정보를 얻을 수 있습니다.
  5. 함수 종속성 ( Function Dependency - 링크 )
    • 함수 종속성이란, 어떤 릴레이션 R의 애트리뷰트 A, B가 있다고 가정할 때, A의 값을 알면 B의 값을 알 수 있는 관계를 말합니다.
    • 이 때 A의 값은 유일해야 하며, B는 중복되도 상관이 없습니다.
    • 즉, 키의 값을 알면 다른 임의의 애트리뷰트 값을 구할 수 있는 것처럼, 키의 성질을 정의한 것이라 할 수 있습니다.
  6. 결합 종속성 ( Join Dependency - 링크 )
    • 결합 종속성이란, 어떤 릴레이션이 여러 개의 릴레이션으로 무손실 분해될 수 있다면, 즉 여러 개의 릴레이션의 결합으로 원래 릴레이션을 만들 수 있는 관계를 말합니다.
    • 예를 들어, A,B,...,C릴레이션 R의 스키마의 부분집합이라고 할 때, A,B,...,C 릴레이션을 결합한 결과와 R이 같은 경우 결합 종속성을 만족시킵니다.
  7. 직교성 ( Orthogonality )
    • 직교성은 여러 개의 릴레이션 사이의 중복제거에 대한 개념입니다.
    • 정규화는 한 개의 릴레이션의 내부에서 중복을 없애는데 초점을 맞춘 작업인 반면, 직교성은 DB 전체에서 중복을 제거하는 작업입니다.




이제 각 정규형에 대해 알아보겠습니다.

일반적으로 BCNF를 목표로 설정하기 때문에 BCNF까지는 자세히 다루고, 그 이후는 개략적으로만 언급하도록 하겠습니다.




4. 제1 정규형, 1NF

1NF를 만족하기 위한 조건은 "릴레이션이어야 한다."는 것이다.

테이블과 릴레이션은 비슷하지만 다른 개념인데, 다음의 과정을 통해 테이블은 릴레이션과 같아집니다.

  • 테이블에는 컬럼이나 행에 순서가 존재하지만, 릴레이션에는 순서가 존재하기 때문에 순서를 고려하지 않습니다.
  • 중복되는 튜플이 존재하지 않음
  • 구체적인 값을 가져야 합니다. 즉 값으로 NULL을 갖지 않습니다.
  • 값은 의미가 있는 한 묶음의 데이터, 즉 원자 단위여야 합니다. ( 원자성 )
    • 원자 단위이려면, 각 행마다 한 컬럼에 하나의 값을 가져야 합니다.
    • 예를 들어, 주소라는 컬럼에 "시, 도, 군, 상세주소"를 몽땅 저장하는 것은 바람직하지 않습니다.





5. 제2 정규형, 2NF

2NF는 후보키의 진부분집합에서 키가 아닌 속성에 대해, 부분 함수 종속성을 제거하는 작업입니다.

즉, 릴레이션이 1NF 조건을 만족하고 부분 함수 종속성을 갖지 않으면, 그 릴레이션은 2NF가 됩니다.



위의 예제에서 정규화를 하기 전 테이블을 보면, 이름과 학과는 후보키입니다.

후보키 중 하나인( 진부분집합 ) 이름을 알면 학년을 알 수 있으므로 함수 종속이 존재하고 있습니다.

2NF를 이러한 함수 종속을 제거하는 작업입니다.


함수 종속을 제거하려면 원래의 릴레이션을 무손실 분해시켜야 합니다.

  • 종속 관계가 있는 속성만 추출해서( projection, 프로젝션 )해서 새로운 릴레이션을 만듭니다.
    • 즉 이름과 학년을 애트리뷰트로 갖는 새로운 릴레이션이 생성됩니다.
  • 기존에 있던 원래 릴레이션은 떨어져나간 애트리뷰트( 학년 )를 제외한 릴레이션으로 존재합니다.
함수 종속을 제거함으로써 이렇게 두 개의 릴레이션으로 쪼개지고, 두 릴레이션을 결합하면 원래의 릴레이션이 되므로 무손실 분해가 이뤄졌습니다.





6. 제3정규형, 3NF

3NF는 추이 함수 종속성( Transitive Dependency )을 제거하는 작업입니다.


추이 함수 종속성은 키가 아닌 애트리뷰트 사이의 함수 종속성을 의미합니다.

예를 들어, 키가 아닌 애트리뷰트 X, Y가 있고, X를 알면 Y값을 알 수 있는 함수 종속성이 있다고 가정해보겠습니다.

3NF는 X와 Y 사이의 함수 종속성을 제거 하는 과정입니다.

2NF는 후보키와 키가 아닌 애트리뷰트 사이의 함수 종속성을 제거했다는 점에서 차이가 있습니다.

참고로 슈퍼키를 알면 X를 알 수 있고, X를 알면 Y를 알 수 있으므로 추이 함수 종속성이라는 말이 붙었습니다.




위의 예제는 후보키인 학번을 알면 우편번호를 알 수 있고, 우편번호를 알면 나머지 주소를 알 수 있기 때문에 추이 함수 종속관계입니다.

따라서 우편번호 애트리뷰트를 기준으로 릴레이션을 분해합니다.

릴레이션을 분해하는 방법은 2NF와 동일합니다.





7. 보이스코드 정규형, BCNF ( 참고 )

BCNF는 키가 아닌 애트리뷰트에서 후보키의 진부부집합에 대한 함수 종속성을 제거하는 작업입니다.




위의 예제는 수강신청 릴레이션입니다.

어떤 학생이 어떤 교수의 교과목을 선택했는지에 대한 애트리뷰트가 있으며, 학번과 교과목이 후보키입니다.


기존의 릴레이션은 3NF를 만족합니다.

어떤 학생이 어떤 교과목을 선택했는지의 조합에따라 교수가 정해지기 때문에 2NF를 만족합니다.

또한 키가 아닌 애트리뷰트인 교수번호를 통해 교수이름을 알 수 있으므로 릴레이션을 분할하여 3NF를 만족합니다.


그런데 교수는 특정 과목만 가르치기 때문에 교수번호를 알면 교과목을 알 수 있는 상황입니다.

이는 2NF, 3NF에서 볼 수 없었던 함수 종속입니다.

따라서 교과목은 후보키로 되어 있고 교수번호는 후보키가 아니므로, 교수번호를 후보키로 지정하고 교과목은 후보키에서 제외합니다.


정리하면 다음과 같습니다.

  • 기존에 (학번, 교과목)을 후보키로 하여, 3NF를 만족하는 수강신청 릴레이션 존재
  • 키 애트리뷰트가 아닌 교수 번호를 통해 후보키인 교과목을 알 수 있음
    • BCNF는 이러한 경우의 함수 종속을 제거합니다.
  • 교수번호를 후보키로 지정, 교과목은 후보키에서 제외


BCNF는 함수 종속성이 모두 제거된 상태의 정규형입니다.

앞서 2NF와 3NF 그리고 BCNF를 거쳐 모든 경우의 수에 대해 함수 종속성을 제거했기 때문입니다.

이로써 BCNF 이상에서 함수 종속성에 의한 무손실 분해를 할 수 없습니다.





8. 4NF, 5NF, 6NF

BCNF까지의 정규화를 진행했다면, 자동으로 5NF의 조건을 만족하는 경우가 많습니다.

그렇기 때문에 일반적으로 BCNF까지만 해도 충분합니다.

이에 따라 BCNF 이후의 정규형은 개략적으로만 살펴보도록 하겠습니다.


1) 4NF 이후 정규화는 어떤 상황에서 진행하는가?

우선 BCNF 이후 정규화가 필요한지 아닌지는 "키가 아닌 애트리뷰트가 존재하는지 여부"입니다.

예를 들어, {A, B, C, X}의 애트리뷰트로 구성된 릴레이션이 있을 때, {A, B, C}를 후보키라 가정하겠습니다.

X값을 알고 싶다면 후보키 (A, B, C)가 필요하며, 이는 함수 종속입니다.

BCNF이면 함수 종속을 해결한 상태이므로 4NF 이상의 정규형을 진행할 필요가 없게 됩니다.



2) 4NF / 5NF / 6NF

흔히 4NF는 다치 종속성( MultiValued Dependency, MVD )을 제거하고 한다고 하지만, 폭 넓게 결합 종속성을 제거하는 과정입니다.

A 애트리뷰트를 알면 X라는 다중값( B, C 애트리뷰트 )을 알 수 있을 때, 이러한 종속성을 제거하는 것입니다. ( 참고 예제 - 링크 )


5NF 역시 결합 종속성을 제거하는 과정입니다.

릴레이션에 애트리뷰트 A, B, C가 있을 때, {A,B}, {B,C}, {A,C} 애트리뷰트 조합을 갖는 릴레이션으로 분해될 수 있을 때, 이러한 결합 종속성을 제거하는 것입니다. ( 참고 예제 - 링크 )


6NF 모든 관계가 후보 키와 하나 이상의 다른 (키 또는 비 키) 속성으로 구성됨을 의미합니다. ( 참고 예제 - 링크, 링크 )

6NF는 직교성에 있어 유용한 정규형이지만, 6NF를 하게 되면 릴레이션이 너무 많아지므로 join을 많이 하게 된다는 단점이 있습니다.





이상으로 정규화에 대해 정리해보았습니다.

정규화는 숙련이 된다면, 정규화 논리에 따라서 기계적인 작업을 반복한다고는 하지만.. 아직은 개념도 어렵네요.


[ 참고 ]

관계형 데이터베이스 실전 입문 - 오쿠노 미키야

https://www.javatpoint.com/dbms-tutorial


댓글 펼치기 👇
  1. 유성민 2019.09.30 21:28

    BCNF 부분에서요 교과목->교수번호에서 부분종속성 있지않나요?
    그럼 2NF 만족 못하는거 아닌가요? 되게 헤깔리네요

    • Favicon of https://victorydntmd.tistory.com victolee 우르르응 2019.10.06 11:43 신고

      BCNF으로 변환하기 전, 3NF 상태일 때 교과목->교수번호에 대한 함수 종속성을 말씀하시는거죠??
      말씀하신대로 예제에서는 2NF를 만족하지 않는 상태인 것 같습니다.

      - 학번 : 00004
      - 교과목 : 알고리즘
      - 교수번호 : 0000D
      필드가 추가 되어야 할 것 같네요.

      지적해주셔서 감사합니다~

  2. 김성준 2020.07.22 09:13

    실무에서 정규화 이론에 의해 DB설계를 하는 습관보단, 업무의 논리적인 부분에 치중해서 설계를 하게 되었었는데 다시 이론적으로 정리할 수 있게 잘 요약해주셔서 많은 도움됐습니다.

  3. Favicon of https://real-012.tistory.com I L G N O Y 2020.10.18 17:39 신고

    최근 정리된 DB 지식들을 보고 있는데, 정말 정리를 잘하시네요. 감사합니다.