BCNF·4NF·5NF 차이: 무손실 분해와 함수 종속 보존 검증하기


1장. 테이블을 잘게 나누면 무조건 좋은 설계일까#

정규화를 배우다 보면 자연스럽게 이런 생각이 생깁니다.

중복이 보이면 더 나누면 되지 않을까?

실제로 1NF, 2NF, 3NF를 거치면서 하나의 거대한 테이블은 여러 개의 작은 테이블로 나뉩니다.

그렇다면 테이블을 계속 나눌수록 좋은 설계가 되는 것일까요?

그렇지 않습니다.

잘못 나눈 테이블을 다시 조인하면 원래 없던 데이터가 만들어질 수도 있습니다.

예를 들어 다음 데이터가 있다고 하겠습니다.

판매자 제품 지역
A X 서울
A Y 부산
B X 부산

이를 판매자와 제품, 제품과 지역, 판매자와 지역이라는 세 관계로 나눴다고 생각해 보겠습니다.

분해된 데이터만 보면 다음 관계가 모두 존재합니다.

A는 X를 판매한다.
A는 부산에서 영업한다.
X는 부산에서 판매되는 제품이다.

이 세 사실을 다시 조인하면 다음 조합이 만들어질 수 있습니다.

A | X | 부산

그런데 원래 데이터에는 이 행이 없었습니다.

즉 데이터를 잃은 것은 아니지만 없던 사실을 만들어 버린 것입니다.

정규화에서 중요한 것은 단순히 테이블을 나누는 일이 아닙니다.

나눈 뒤에도 원래 데이터의 의미를 정확하게 복원할 수 있는가?

이 질문이 고급 정규형의 핵심입니다.


2장. 3NF 이후에도 문제가 남을 수 있다#

3NF까지 정규화하면 많은 중복과 갱신 이상을 제거할 수 있습니다.

하지만 3NF가 모든 종류의 데이터 중복을 해결하는 것은 아닙니다.

대표적으로 다음 문제가 남을 수 있습니다.

함수 종속 문제
→ BCNF

서로 독립적인 여러 값의 반복 문제
→ 4NF

세 개 이상의 관계가 조합되면서 생기는 문제
→ 5NF

정규형의 번호가 올라간다는 사실보다 어떤 종류의 종속을 다루는가를 이해하는 것이 중요합니다.


3장. BCNF는 3NF보다 결정자 조건이 더 엄격하다#

BCNF는 Boyce-Codd Normal Form의 약자입니다.

핵심 조건은 매우 간단합니다.

비자명한 함수 종속이 다음처럼 존재한다고 하겠습니다.

X → Y

BCNF를 만족하려면 X가 슈퍼키여야 합니다.

즉:

모든 결정자
→ 슈퍼키

여야 합니다.

3NF와 비교하면 BCNF의 차이가 분명해집니다.

3NF에서는 비자명한 함수 종속 X → A에 대해 다음 둘 중 하나를 만족하면 됩니다.

X가 슈퍼키

또는

A가 주속성

BCNF에서는 두 번째 예외가 없습니다.

X가 슈퍼키

여야 합니다.


4장. 3NF는 만족하지만 BCNF는 위반하는 사례#

다음 테이블을 생각해 보겠습니다.

배정
- 학생ID
- 과목코드
- 교수ID

업무 규칙은 다음과 같습니다.

한 학생은 특정 과목에서 한 교수에게만 배정된다.

교수 한 명은 하나의 과목만 담당한다.

함수 종속으로 표현하면 다음과 같습니다.

(학생ID, 과목코드) → 교수ID

교수ID → 과목코드

예제 데이터는 다음과 같습니다.

학생ID 과목코드 교수ID
S1 C1 P1
S1 C2 P3
S2 C1 P2

5장. 후보키를 먼저 계산해 보자#

다음 조합에서 시작합니다.

(학생ID, 과목코드)

첫 번째 함수 종속으로 교수ID를 얻을 수 있습니다.

(학생ID, 과목코드)
→
교수ID

따라서 세 속성 모두 결정할 수 있습니다.

즉 후보키가 될 수 있습니다.

이번에는 다음 조합을 보겠습니다.

(학생ID, 교수ID)

교수ID를 통해 과목코드를 얻습니다.

교수ID → 과목코드

따라서 역시 전체 속성을 결정할 수 있습니다.

결과적으로 후보키는 다음 두 개입니다.

(학생ID, 과목코드)

(학생ID, 교수ID)

6장. 왜 3NF는 만족하고 BCNF는 위반할까#

문제가 되는 함수 종속은 다음입니다.

교수ID → 과목코드

교수ID만으로 전체 행을 식별할 수 있을까요?

아닙니다.

같은 교수가 여러 학생을 담당할 수 있습니다.

따라서 교수ID는 슈퍼키가 아닙니다.

BCNF 조건을 위반합니다.

하지만 과목코드는 후보키 (학생ID, 과목코드)에 포함됩니다.

즉 과목코드는 주속성입니다.

따라서 3NF에서는 허용될 수 있습니다.

함수 종속 결정자가 슈퍼키 종속 속성이 주속성 3NF BCNF
(학생ID, 과목코드) → 교수ID 예 예 만족 만족
교수ID → 과목코드 아니오 예 만족 위반

이것이 3NF와 BCNF의 대표적인 차이입니다.


7장. BCNF 위반이 실제로 어떤 문제를 만들까#

다음 데이터가 있다고 하겠습니다.

학생ID 과목코드 교수ID
S1 C1 P1
S2 C1 P1
S3 C1 P1

P1 교수의 담당 과목이 C1에서 C3로 바뀌었다고 하겠습니다.

그러면 P1이 등장하는 모든 행을 수정해야 합니다.

P1 | C1
P1 | C1
P1 | C1

을 모두:

P1 | C3

으로 바꿔야 합니다.

하나라도 놓치면 같은 교수에게 서로 다른 과목이 연결됩니다.

즉 결정자가 슈퍼키가 아닌 상태에서 같은 사실이 여러 행에 반복되면서 갱신 이상이 발생합니다.


8장. BCNF로 분해해 보자#

다음 함수 종속이 문제였습니다.

교수ID → 과목코드

따라서 교수와 담당과목을 별도 테이블로 분리할 수 있습니다.

교수담당#

교수ID 과목코드
P1 C1
P2 C1
P3 C2

학생교수#

학생ID 교수ID
S1 P1
S1 P3
S2 P2

ERD로 표현하면 다음과 같습니다.

erDiagram
    COURSE ||--o{ PROFESSOR_ASSIGNMENT : assigned
    PROFESSOR_ASSIGNMENT ||--o{ STUDENT_PROFESSOR : referenced

    COURSE {
        string course_code PK
    }

    PROFESSOR_ASSIGNMENT {
        string professor_id PK
        string course_code FK
    }

    STUDENT_PROFESSOR {
        string student_id PK
        string professor_id PK, FK
    }

이제 교수의 담당과목은 한 곳에서 관리됩니다.


9장. 그런데 BCNF 분해 후 다른 문제가 생길 수 있다#

원래 업무 규칙에는 다음 함수 종속도 있었습니다.

(학생ID, 과목코드) → 교수ID

즉 한 학생이 같은 과목에 두 교수에게 동시에 배정될 수 없다는 규칙입니다.

분해된 테이블에 다음 데이터를 추가해 보겠습니다.

교수담당:

P4 | C1

학생교수:

S1 | P4

각 테이블만 보면 문제가 없습니다.

하지만 두 테이블을 조인하면 다음 두 행이 존재할 수 있습니다.

S1 | C1 | P1

S1 | C1 | P4

한 학생 S1이 같은 과목 C1에 두 교수에게 배정되었습니다.

원래 함수 종속을 위반합니다.

즉 BCNF 분해는 가능했지만 원래의 모든 함수 종속을 각 테이블에서 독립적으로 검사할 수는 없게 되었습니다.

여기서 함수 종속 보존의 개념이 중요해집니다.


10장. 무손실 분해와 함수 종속 보존은 다른 문제다#

테이블을 분해한 뒤에는 최소한 두 가지를 확인해야 합니다.

무손실 분해#

분해한 테이블을 다시 조인했을 때 원래 데이터가 정확하게 복원되는가?

함수 종속 보존#

분해된 각각의 테이블에 제약을 적용하는 것만으로 원래 함수 종속을 모두 검사할 수 있는가?

둘은 같은 개념이 아닙니다.

무손실 분해
→ 데이터 복원 문제

함수 종속 보존
→ 제약 검증 문제

무손실이면서 함수 종속이 완전히 보존되지 않을 수도 있습니다.


11장. 무손실 분해란 무엇인가#

원래 릴레이션이 다음과 같다고 하겠습니다.

R(A, B, C)

이를 다음처럼 분해합니다.

R1(A, B)

R2(B, C)

원래 데이터가 다음과 같습니다.

A B C
a1 b1 c1
a2 b2 c2

분해하면:

R1:

A B
a1 b1
a2 b2

R2:

B C
b1 c1
b2 c2

다시 B로 조인하면 정확히 원래 두 행이 복원됩니다.

a1 | b1 | c1

a2 | b2 | c2

이것이 무손실 분해입니다.


12장. 잘못 분해하면 가짜 튜플이 생긴다#

다음 원본을 보겠습니다.

A B C
a1 b1 c1
a2 b1 c2

이를 마찬가지로 분해합니다.

R1:

A B
a1 b1
a2 b1

R2:

B C
b1 c1
b1 c2

다시 조인하면 어떻게 될까요?

a1 | b1 | c1
a1 | b1 | c2
a2 | b1 | c1
a2 | b1 | c2

원래는 두 행뿐이었습니다.

그런데 네 행이 생겼습니다.

다음 두 행은 원래 존재하지 않았습니다.

a1 | b1 | c2

a2 | b1 | c1

이러한 행을 가짜 튜플이라고 합니다.

테이블을 분해하면서 정보가 모호해져 잘못된 조합이 만들어진 것입니다.


13장. 두 테이블 분해에서 무손실성을 판단하는 기준#

릴레이션 R을 R1과 R2로 분해했다고 하겠습니다.

공통 속성은 다음입니다.

R1 ∩ R2

일반적으로 주어진 함수 종속으로 다음 중 하나가 성립하면 무손실 분해를 판단할 수 있습니다.

(R1 ∩ R2) → R1

또는

(R1 ∩ R2) → R2

쉽게 말하면 다음과 같습니다.

두 테이블의 공통 속성이 둘 중 한 테이블의 행을 식별할 수 있는가?

공통 속성이 한쪽 테이블의 키 역할을 할 수 있다면 잘못된 조합이 생길 가능성을 막을 수 있습니다.


14장. 함수 종속 보존은 왜 중요한가#

원래 릴레이션에 다음 규칙이 있었다고 하겠습니다.

A → C

그런데 분해 후 A와 C가 어느 테이블에서도 직접 연결되지 않는다면 이 규칙을 검사하려면 두 테이블을 조인해야 할 수 있습니다.

데이터를 INSERT하거나 UPDATE할 때마다 다른 테이블까지 조인해 제약조건을 검사해야 한다면 비용과 복잡성이 높아집니다.

따라서 함수 종속 보존은 다음 질문과 연결됩니다.

원래의 데이터 규칙을 분해된 테이블 각각의 제약으로 유지할 수 있는가?


15장. BCNF와 3NF 사이에는 실제 설계 선택이 존재한다#

BCNF는 더 강한 정규형입니다.

그러나 BCNF 분해 과정에서 함수 종속 보존이 어려워질 수 있습니다.

반면 3NF 분해는 적절한 합성 방법을 사용하면 무손실성과 함수 종속 보존을 함께 확보할 수 있습니다.

따라서 실제 설계에서는 단순히 다음처럼 생각해서는 안 됩니다.

BCNF가 3NF보다 숫자가 높다.

따라서 BCNF가 항상 더 좋다.

고려해야 할 것은 다음입니다.

중복 제거 효과

무손실성

함수 종속 보존

제약 검사 비용

실제 업무 변경 패턴

정규형은 점수가 아니라 설계 조건입니다.


16장. 4NF는 여러 개의 독립적인 다중값을 다룬다#

이제 함수 종속과 다른 문제가 등장합니다.

교수 P1이 다음 두 과목을 담당한다고 하겠습니다.

C1
C2

그리고 다음 두 자격증을 가지고 있습니다.

Q1
Q2

과목과 자격이 서로 완전히 독립적이라고 가정합니다.

하나의 테이블에 모두 저장하면 다음과 같습니다.

교수ID 과목코드 자격코드
P1 C1 Q1
P1 C1 Q2
P1 C2 Q1
P1 C2 Q2

과목은 두 개입니다.

자격도 두 개입니다.

그런데 행은 네 개가 필요합니다.

2 × 2 = 4

이유는 서로 독립적인 두 다중값의 모든 조합을 한 테이블에 저장했기 때문입니다.


17장. 자격 하나를 추가하면 중복이 더 커진다#

P1이 새로운 자격 Q3을 취득했다고 하겠습니다.

과목 C1과 C2가 모두 그대로 존재하므로 다음 두 행을 추가해야 합니다.

P1 | C1 | Q3

P1 | C2 | Q3

새로운 사실은 단 하나입니다.

P1이 Q3 자격을 취득했다.

그런데 과목 수만큼 행을 추가해야 합니다.

과목과 자격이라는 두 독립적인 사실을 하나의 테이블에 섞었기 때문입니다.


18장. 다치 종속은 독립적인 여러 값을 표현한다#

이런 상황을 다치 종속으로 표현할 수 있습니다.

기호는 다음과 같습니다.

X ↠ Y

P1 교수에 대해 과목과 자격이 독립적이라면 다음과 같이 생각할 수 있습니다.

교수ID ↠ 과목코드

교수ID ↠ 자격코드

뜻은 다음과 같습니다.

한 교수에 대해 여러 과목 값과 여러 자격 값이 서로 독립적으로 존재한다.

이를 그림으로 보면 더 쉽게 이해할 수 있습니다.

erDiagram
    PROFESSOR ||--o{ PROFESSOR_COURSE : teaches
    PROFESSOR ||--o{ PROFESSOR_CERTIFICATION : owns

    PROFESSOR {
        string professor_id PK
        string professor_name
    }

    PROFESSOR_COURSE {
        string professor_id PK, FK
        string course_code PK
    }

    PROFESSOR_CERTIFICATION {
        string professor_id PK, FK
        string certification_code PK
    }

19장. 4NF는 다치 종속의 결정자가 슈퍼키인지 본다#

4NF의 핵심 조건은 다음과 같습니다.

비자명한 다치 종속이:

X ↠ Y

로 존재한다면 X가 슈퍼키여야 합니다.

앞의 교수정보 테이블에서 교수ID 하나는 전체 행을 식별하지 못합니다.

한 교수에게 여러 과목과 여러 자격 조합이 있기 때문입니다.

따라서 4NF를 위반할 수 있습니다.


20장. 4NF에서는 독립적인 다중값을 분리한다#

원래 테이블:

교수ID 과목코드 자격코드
P1 C1 Q1
P1 C1 Q2
P1 C2 Q1
P1 C2 Q2

이를 두 테이블로 나눕니다.

교수과목#

교수ID 과목코드
P1 C1
P1 C2

교수자격#

교수ID 자격코드
P1 Q1
P1 Q2

이제 새로운 자격 Q3을 추가하려면 다음 한 행만 넣으면 됩니다.

P1 | Q3

불필요한 조합 반복이 사라졌습니다.


21장. 4NF 분해의 전제는 독립성이다#

여기서 가장 중요한 조건이 있습니다.

과목과 자격이 정말 독립적이어야 합니다.

예를 들어 업무 규칙이 다음과 같다고 해보겠습니다.

Q1 자격이 있어야 C1을 가르칠 수 있다.

Q2 자격이 있어야 C2를 가르칠 수 있다.

실제 허용 조합이 다음뿐이라면:

C1 | Q1

C2 | Q2

과목과 자격은 독립적이지 않습니다.

두 목록으로 분리한 뒤 다시 조인하면:

C1 | Q1
C1 | Q2
C2 | Q1
C2 | Q2

가 됩니다.

원래 허용되지 않았던 조합이 생깁니다.

따라서 4NF에서 가장 중요한 질문은 이것입니다.

두 다중값은 정말 서로 독립적인가?


22장. 자격과 언어 사례로 다시 보면 더 명확하다#

직원 E001이 다음 자격을 가지고 있다고 하겠습니다.

A
B

그리고 다음 언어를 사용할 수 있습니다.

한국어
영어

두 능력이 서로 독립적이라면:

A + 한국어
A + 영어
B + 한국어
B + 영어

모두 의미가 있습니다.

이 경우 자격과 언어를 각각 별도 테이블로 관리하는 것이 자연스럽습니다.

erDiagram
    EMPLOYEE ||--o{ EMPLOYEE_CERTIFICATION : owns
    EMPLOYEE ||--o{ EMPLOYEE_LANGUAGE : speaks

    EMPLOYEE {
        string employee_id PK
    }

    EMPLOYEE_CERTIFICATION {
        string employee_id PK, FK
        string certification_code PK
    }

    EMPLOYEE_LANGUAGE {
        string employee_id PK, FK
        string language_code PK
    }

하지만 업무가 다음처럼 연결되어 있다면 상황이 달라집니다.

A 자격으로는 한국어 업무만 가능

B 자격으로는 영어 업무만 가능

이 경우 자격 + 언어 조합 자체가 중요한 사실입니다.

분리하면 안 됩니다.


23장. 5NF는 더 복잡한 조인 종속을 다룬다#

4NF가 독립적인 다중값 문제를 다룬다면, 5NF는 더 복잡한 조인 종속을 다룹니다.

대표적으로 세 개 이상의 속성 관계를 여러 개의 작은 관계로 분해했을 때 문제가 발생할 수 있습니다.

다음 테이블을 보겠습니다.

판매가능
- 판매자
- 제품
- 지역

한 행의 의미는 다음과 같습니다.

이 판매자가 이 지역에서 이 제품을 판매할 수 있다.


24장. 세 속성 관계를 쌍으로 나누면 정말 안전할까#

원본 데이터는 다음과 같습니다.

판매자 제품 지역
A X 서울
A Y 부산
B X 부산

이를 다음 세 관계로 분해해 보겠습니다.

판매자제품#

판매자 제품
A X
A Y
B X

제품지역#

제품 지역
X 서울
Y 부산
X 부산

판매자지역#

판매자 지역
A 서울
A 부산
B 부산

각 테이블만 보면 모두 원본에서 얻은 사실입니다.


25장. 세 테이블을 다시 조인하면 없던 권한이 생길 수 있다#

다음 세 사실이 있습니다.

A는 X를 취급한다.

X는 부산에서 판매된다.

A는 부산에서 영업한다.

세 관계를 조인하면:

A | X | 부산

이 생성될 수 있습니다.

하지만 원본에는 다음 행이 없었습니다.

A | X | 부산

즉 A가 부산에서 X를 판매할 수 있다는 사실을 실제로 승인한 적이 없습니다.

단순히 쌍별 관계가 각각 존재한다는 이유만으로 세 값의 조합까지 자동으로 허용되는 것은 아닙니다.


26장. 가짜 튜플은 단순한 행 증가가 아니라 잘못된 업무 사실이다#

A | X | 부산이라는 가짜 튜플을 단순히 데이터 한 행이 늘었다고 생각하면 문제의 심각성을 놓칠 수 있습니다.

이 데이터를 실제 권한 테이블이라고 생각해 보겠습니다.

원래는 A 판매자에게 부산에서 X를 판매할 권한이 없었습니다.

그런데 분해한 테이블을 조인한 결과 권한이 생겼습니다.

즉 데이터베이스가 다음을 잘못 허용할 수 있습니다.

승인되지 않은 판매

승인되지 않은 서비스 제공

승인되지 않은 권한

존재하지 않는 계약 조합

무손실 분해가 중요한 이유입니다.


27장. 조인 종속은 작은 관계의 조인으로 원본을 정확히 복원할 수 있다는 규칙이다#

만약 업무 규칙이 다음과 같다면 이야기가 달라집니다.

판매자와 제품 관계가 허용되고, 제품과 지역 관계가 허용되고, 판매자와 지역 관계가 허용되면 세 값의 조합도 반드시 허용된다.

이 규칙이 실제 업무에서 항상 성립한다면 세 개의 관계를 다시 조인했을 때 원본이 정확하게 복원됩니다.

이런 관계를 조인 종속과 연결해 이해할 수 있습니다.

5NF는 이러한 조인 종속 때문에 발생하는 중복을 더 작은 관계로 분해할 수 있는지를 다룹니다.


28장. 5NF는 무조건 세 개의 테이블로 나누라는 뜻이 아니다#

5NF를 다음처럼 오해하면 안 됩니다.

세 속성이 있으면 세 테이블로 나눈다.

그렇지 않습니다.

먼저 업무에서 다음 규칙이 성립해야 합니다.

작은 관계들의 조합만으로 원래 관계를 정확하게 결정할 수 있다.

이 규칙이 없다면 분해해서는 안 됩니다.

다시 말해 5NF는 조인 결과에 새로운 사실이 생기지 않는다는 업무 규칙이 있을 때 의미가 있습니다.


29장. 5NF 구조를 ERD 관점으로 바라보기#

판매자·제품·지역의 조합 자체가 업무 사실이라면 다음처럼 관계 개체를 유지하는 것이 자연스럽습니다.

erDiagram
    SELLER ||--o{ SALES_PERMISSION : has
    PRODUCT ||--o{ SALES_PERMISSION : allowed
    REGION ||--o{ SALES_PERMISSION : applies

    SELLER {
        string seller_id PK
    }

    PRODUCT {
        string product_id PK
    }

    REGION {
        string region_id PK
    }

    SALES_PERMISSION {
        string seller_id PK, FK
        string product_id PK, FK
        string region_id PK, FK
    }

SALES_PERMISSION의 한 행 자체가 다음 사실을 의미합니다.

판매자 A가
제품 X를
지역 부산에서
판매할 수 있다.

이 세 값의 조합이 중요한 사실이라면 억지로 쌍별 관계로 분해할 이유가 없습니다.


30장. 무손실 분해는 원래 행이 모두 돌아오는지만 보면 안 된다#

분해 후 조인한 결과가 다음과 같다고 하겠습니다.

원본:

3행

조인 결과:

4행

원본 3행이 모두 들어 있습니다.

그렇다면 정보 손실이 없으니 괜찮을까요?

아닙니다.

가짜 튜플 1개가 추가되었습니다.

무손실 분해의 의미는 다음입니다.

원본 ⊆ 조인결과

만 만족하는 것이 아닙니다.

정확하게:

원본 = 조인결과

여야 합니다.

즉 빠진 행도 없어야 하고 추가된 행도 없어야 합니다.


31장. 함수 종속 보존은 실제 운영 비용과 연결된다#

원래 테이블에서는 다음 제약을 한 번에 검사할 수 있었다고 하겠습니다.

(학생ID, 과목코드) → 교수ID

BCNF 분해 후에는 학생ID와 교수ID가 한 테이블에 있고, 교수ID와 과목코드가 다른 테이블에 있습니다.

한 학생이 같은 과목에 두 교수를 배정받았는지 확인하려면 두 테이블을 함께 봐야 합니다.

즉 데이터 입력 때마다 조인이나 별도 검증 로직이 필요할 수 있습니다.

함수 종속 보존이 중요한 이유는 단순한 이론적 조건이 아닙니다.

제약을 어디에서 검사할 것인가?

한 테이블의 UNIQUE로 가능한가?

여러 테이블을 조인해야 하는가?

애플리케이션에서 검증해야 하는가?

와 직접 연결됩니다.


32장. 함수 종속 보존 여부는 단순히 열 배치만 보고 판단하지 않는다#

다음 함수 종속이 있다고 하겠습니다.

A → B

B → C

C → A

이를 다음처럼 나눕니다.

R1(A, B)

R2(B, C)

겉으로 보면 C → A가 어느 테이블에도 직접 들어 있지 않습니다.

그래서 종속이 사라졌다고 생각할 수 있습니다.

하지만 원래 함수 종속을 이용하면:

C → A → B

이므로:

C → B

도 성립합니다.

R2에서 C와 B의 관계를 얻고, R1에서 B와 A의 관계를 이용하면 원래 종속을 다시 유도할 수 있습니다.

따라서 함수 종속 보존은 단순히 같은 열이 한 테이블에 있는지만 확인해서는 안 됩니다.

분해된 관계에서 유도 가능한 함수 종속 전체를 봐야 합니다.


33장. BCNF·4NF·5NF를 한 번에 비교하기#

정규형 주로 다루는 종속 핵심 질문 대표 문제
BCNF 함수 종속 모든 결정자가 슈퍼키인가 교수ID가 과목을 결정
4NF 다치 종속 독립적인 다중값을 한 표에서 곱하고 있는가 교수의 과목과 자격
5NF 조인 종속 더 작은 관계의 조인만으로 원본을 정확하게 복원할 수 있는가 판매자·제품·지역

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

BCNF
→ 결정자 문제

4NF
→ 독립적인 여러 목록 문제

5NF
→ 여러 관계를 조인할 때 생기는 조합 문제

34장. 1NF부터 5NF까지 흐름으로 보면#

정규형 주로 확인하는 문제
1NF 반복값과 속성 값의 구조
2NF 복합 후보키 일부에 대한 종속
3NF 슈퍼키가 아닌 결정자와 비주속성의 종속
BCNF 모든 비자명한 함수 종속의 결정자
4NF 독립적인 다치 종속
5NF 비자명한 조인 종속

정규형은 단순히 테이블을 계속 쪼개는 단계가 아닙니다.

단계마다 서로 다른 종류의 데이터 종속을 확인합니다.


35장. 교수·학과·과목 데이터를 실제로 분해해 보자#

다음 테이블이 있다고 하겠습니다.

교수ID 교수명 학과코드 학과명 연구실 과목코드 과목명 강의시간
P1 가람 D1 컴퓨터 301호 C1 DB 월 09시
P1 가람 D1 컴퓨터 301호 C2 운영체제 수 10시
P2 나래 D1 컴퓨터 301호 C1 DB 목 14시

업무 규칙은 다음과 같다고 하겠습니다.

교수ID → 교수명, 학과코드

학과코드 → 학과명, 연구실

과목코드 → 과목명

(교수ID, 과목코드) → 강의시간

36장. 후보키를 계산해 보자#

교수ID만으로는 과목을 알 수 없습니다.

교수ID+
→
교수명
학과코드
학과명
연구실

과목코드와 강의시간은 얻지 못합니다.

과목코드만으로도 교수 정보를 얻을 수 없습니다.

반면 다음 조합은:

(교수ID, 과목코드)

모든 속성을 결정합니다.

따라서 후보키입니다.


37장. 부분 함수 종속부터 제거한다#

후보키는:

(교수ID, 과목코드)

인데 다음 속성은 교수ID 하나만으로 결정됩니다.

교수ID → 교수명, 학과코드

과목명은 과목코드만으로 결정됩니다.

과목코드 → 과목명

복합 후보키의 일부에 대한 종속입니다.

따라서 교수와 과목을 분리할 수 있습니다.


38장. 학과 정보에도 이행 종속이 존재한다#

다음 종속이 있습니다.

교수ID → 학과코드

학과코드 → 학과명, 연구실

교수ID를 통해 학과코드를 거쳐 학과명과 연구실이 결정됩니다.

따라서 학과도 별도 테이블로 분리할 수 있습니다.


39장. 최종 구조를 ERD로 보면#

erDiagram
    DEPARTMENT ||--o{ PROFESSOR : has
    PROFESSOR ||--o{ LECTURE : teaches
    COURSE ||--o{ LECTURE : scheduled

    DEPARTMENT {
        string department_code PK
        string department_name
        string office
    }

    PROFESSOR {
        string professor_id PK
        string professor_name
        string department_code FK
    }

    COURSE {
        string course_code PK
        string course_name
    }

    LECTURE {
        string professor_id PK, FK
        string course_code PK, FK
        string lecture_time
    }

각 테이블의 책임은 다음과 같습니다.

DEPARTMENT
→ 학과 정보

PROFESSOR
→ 교수 정보

COURSE
→ 과목 정보

LECTURE
→ 특정 교수가 특정 과목을 강의하는 관계

이제 교수 이름, 학과명, 과목명을 여러 강의 행에 반복할 필요가 없습니다.


40장. 다치 종속과 조인 종속을 혼동하지 말자#

4NF와 5NF가 헷갈리는 이유는 둘 다 여러 값의 조합을 다루기 때문입니다.

차이를 간단히 보면 다음과 같습니다.

4NF#

한 대상에 서로 독립적인 두 종류의 다중값이 존재합니다.

교수
→ 여러 과목

교수
→ 여러 자격

문제는 두 목록의 불필요한 곱입니다.

5NF#

세 개 이상의 관계를 여러 쌍으로 나눴을 때 조인 결과가 원래 관계를 정확하게 복원하는지가 문제입니다.

판매자
제품
지역

문제는 작은 관계들의 조합이 원래 없던 사실을 만들 수 있다는 점입니다.


41장. 고급 정규형을 적용하기 전에 반드시 업무 의미를 확인해야 한다#

고급 정규화에서는 데이터 모양만 보고 종속을 추정하는 것이 특히 위험합니다.

예를 들어 다음 테이블이 있습니다.

직원 | 자격 | 언어

모든 조합이 현재 데이터에 존재한다고 해서 반드시 독립적이라는 의미는 아닙니다.

현재 우연히 모든 조합이 존재할 수도 있습니다.

업무 규칙으로 다음을 확인해야 합니다.

자격과 언어는 서로 관계없이 독립적으로 부여되는가?

마찬가지로:

판매자 | 제품 | 지역

을 세 쌍으로 분해하려면 다음을 확인해야 합니다.

세 쌍의 관계가 존재하면 세 값의 조합도 항상 유효한가?

정규화는 데이터 패턴이 아니라 업무 규칙을 기준으로 해야 합니다.


42장. 분해 전후를 실제 데이터로 검증하는 방법#

고급 정규형에서는 수식만으로 끝내지 말고 작은 데이터로 실제 테스트를 해보는 것이 좋습니다.

다음 절차가 유용합니다.

1단계#

원본 데이터를 몇 행 작성합니다.

2단계#

분해할 테이블에 각각 투영합니다.

3단계#

분해된 테이블을 다시 조인합니다.

4단계#

원본과 조인 결과를 비교합니다.

확인할 것은 두 가지입니다.

원본에 있었는데 사라진 행이 있는가?

원본에 없었는데 새로 생긴 행이 있는가?

둘 다 없어야 정확한 복원입니다.


43장. SQL로 가짜 튜플을 확인할 수도 있다#

분해 전 원본과 다시 조인한 결과가 있다면 집합 차이를 이용해 확인할 수 있습니다.

개념적으로는 다음 두 검사를 수행합니다.

원본 - 복원결과

결과가 있으면 원래 행을 잃은 것입니다.

그리고:

복원결과 - 원본

결과가 있으면 가짜 튜플이 생긴 것입니다.

즉 두 결과가 모두 공집합이어야 합니다.

원본 - 복원결과 = ∅

복원결과 - 원본 = ∅

그래야 원본과 복원 결과가 정확하게 같습니다.


44장. 높은 정규형이 항상 빠른 데이터베이스를 의미하지는 않는다#

정규화를 많이 하면 중복과 갱신 이상을 줄일 수 있습니다.

하지만 조회 시 조인이 증가할 수 있습니다.

예를 들어 하나의 화면에 다음 정보가 필요하다고 하겠습니다.

교수명
학과명
과목명
강의시간

정규화된 구조에서는 여러 테이블을 조인해야 할 수 있습니다.

그렇다고 정규화가 잘못된 것은 아닙니다.

정규화는 주로 데이터의 의미와 일관성을 다루는 설계 기준입니다.

성능은 데이터 규모, 인덱스, 실행 계획, 캐시, 접근 패턴 등을 별도로 측정해야 합니다.


45장. 정규화를 성능 문제와 혼동하지 말자#

다음 두 질문은 서로 다릅니다.

이 데이터 구조가 논리적으로 올바른가?

이 구조가 현재 업무에서 충분히 빠른가?

첫 번째는 정규화와 관련됩니다.

두 번째는 성능 설계와 관련됩니다.

정규화가 잘된 구조가 느릴 수도 있고, 중복이 많은 구조가 특정 조회에서는 빠를 수도 있습니다.

그러나 조회가 빠르다는 이유만으로 데이터 중복과 갱신 책임을 아무 규칙 없이 늘리는 것은 위험합니다.


46장. BCNF·4NF·5NF를 판단할 때 사용할 체크 순서#

고급 정규형을 검토할 때는 다음 순서로 접근할 수 있습니다.

  1. 한 행이 무엇을 의미하는지 정의합니다.
  2. 후보키를 계산합니다.
  3. 함수 종속을 적습니다.
  4. 모든 비자명한 함수 종속의 결정자가 슈퍼키인지 확인합니다.
  5. 독립적인 여러 다중값이 존재하는지 확인합니다.
  6. 다치 종속이 업무상 실제로 성립하는지 확인합니다.
  7. 세 개 이상의 관계를 작은 관계로 분해할 근거가 있는지 확인합니다.
  8. 분해 후 다시 조인해 원본이 정확히 복원되는지 확인합니다.
  9. 가짜 튜플이 생기지 않는지 확인합니다.
  10. 원래 함수 종속을 분해된 테이블의 제약만으로 검사할 수 있는지 확인합니다.

이 순서를 따르면 정규형 이름만 외우는 것보다 훨씬 정확한 판단을 할 수 있습니다.


47장. 정규형별 핵심 질문을 기억하자#

BCNF를 볼 때는 다음 질문을 합니다.

이 값을 결정하는 X가 정말 슈퍼키인가?

4NF에서는 다음을 묻습니다.

한 대상에 존재하는 여러 값의 집합이 서로 독립적인가?

5NF에서는 다음을 묻습니다.

관계를 더 작은 테이블로 나눈 뒤 다시 조인해도 원래 사실만 정확하게 복원되는가?

그리고 모든 분해에서는 공통적으로 다음 두 질문이 필요합니다.

분해는 무손실인가?

원래 제약은 보존되는가?


48장. 핵심 정리#

BCNF·4NF·5NF는 단순히 3NF보다 높은 단계라는 이유로 사용하는 정규형이 아닙니다.

각각 서로 다른 종류의 종속 문제를 다룹니다.

BCNF
→ 함수 종속

4NF
→ 다치 종속

5NF
→ 조인 종속

BCNF에서는 모든 비자명한 함수 종속의 결정자가 슈퍼키여야 합니다.

3NF는 종속 속성이 주속성인 경우를 허용할 수 있지만 BCNF는 결정자가 슈퍼키인지 더 엄격하게 확인합니다.

4NF에서는 한 대상에 존재하는 여러 다중값이 서로 독립적인데 한 테이블에서 모든 조합으로 반복되고 있는지를 확인합니다.

5NF에서는 세 개 이상의 관계를 더 작은 관계로 분해했을 때 다시 조인하여 원래 관계를 정확하게 복원할 수 있는지를 확인합니다.

그리고 고급 정규화를 적용할 때 반드시 구분해야 하는 두 개념이 있습니다.

무손실 분해
→ 원래 데이터를 정확하게 복원할 수 있는가

함수 종속 보존
→ 원래 제약을 분해된 테이블만으로 검사할 수 있는가

무손실 분해라고 해서 함수 종속이 자동으로 보존되는 것은 아닙니다.

함수 종속을 잘 보존한다고 해서 아무 분해나 안전한 것도 아닙니다.

분해 결과를 다시 조인했을 때 원래 없던 행이 만들어지는지도 확인해야 합니다.

특히 4NF와 5NF에서는 독립성에 대한 업무 가정이 중요합니다.

자격과 언어가 정말 독립적인지, 판매자와 제품과 지역의 쌍별 관계가 실제 세 값의 조합까지 보장하는지를 확인하지 않은 채 분해하면 데이터베이스가 존재하지 않았던 사실을 만들어낼 수 있습니다.

고급 정규화에서 가장 중요한 질문은 결국 하나로 모입니다.

테이블을 나눈 뒤에도 원래 데이터가 표현하던 사실과 업무 규칙을 정확하게 유지할 수 있는가?

중복을 줄이는 것보다 이 질문에 정확하게 답하는 것이 더 중요합니다.

이 페이지의 목차