정규화(Normalization)는 데이터의 중복을 줄이고 이상 현상(Anomaly)을 방지하기 위한 데이터베이스 설계 기법이다. 관계형 데이터베이스에서 데이터를 효율적이고 논리적으로 구조화하는 데 목적이 있다. 즉, 중복된 데이터를 없애고 테이블 간의 관계를 정리해서 데이터 무결성과 저장 효율성을 높이기 위한 과정이다.
정규화를 하지 않으면 다음과 같은 문제가 발생할 수 있다.
학생ID | 이름 | 과목 | 교수명 | 학과코드 | 학과명 |
---|---|---|---|---|---|
1 | 홍길동 | C, C++ | 김교수 | CS | 컴퓨터공학과 |
2 | 이순신 | C++ | 김교수 | CS | 컴퓨터공학과 |
3 | 강감찬 | JAVA | 이교수 | EE | 전자공학과 |
C++
과목 교수명이 변경되면 모든 C++
행을 갱신해야 함 -> 갱신 이상 발생 가능JAVA
수업이 폐강되어 행을 삭제하면 강감찬
학생 정보까지 사라질 수 있음 -> 삭제 이상제 1정규화란 테이블의 컬럼이 원자값(Atomic Value)을 갖도록 테이블을 분해하는 것이다. 아래와 같은 규칙들을 만족해야 한다.
예시 테이블을 제 1정규화를 진행한 테이블은 아래와 같다.
학생ID | 이름 | 과목 | 교수명 | 학과코드 | 학과명 |
---|---|---|---|---|---|
1 | 홍길동 | C | 김교수 | CS | 컴퓨터공학과 |
1 | 홍길동 | C++ | 김교수 | CS | 컴퓨터공학과 |
2 | 이순신 | C++ | 김교수 | CS | 컴퓨터공학과 |
3 | 강감찬 | JAVA | 이교수 | EE | 전자공학과 |
제 2정규화란 제 1정규화를 진행한 테이블에 대해 완전 함수 종속을 만족하도록 테이블을 분해하는 것이다. 여기서 완전 함수 종속이라는 것은 기본키의 부분 집합이 결정자가 되어선 안된다는 것을 의미한다. 아래와 같은 규칙을 만족해야 한다.
제 1정규화 테이블을 예시로 들자면
학생ID | 이름 | 과목 | 교수명 | 학과코드 | 학과명 |
---|---|---|---|---|---|
1 | 홍길동 | C | 김교수 | CS | 컴퓨터공학과 |
1 | 홍길동 | C++ | 김교수 | CS | 컴퓨터공학과 |
2 | 이순신 | C++ | 김교수 | CS | 컴퓨터공학과 |
3 | 강감찬 | JAVA | 이교수 | EE | 전자공학과 |
위 테이블에서는 학생 정보가 과목과는 상관없이 중복 저장되고 있다. 이는 기본키 (학생ID, 과목)
중 학생ID
에만 의존하는 컬럼들이 존재한다는 뜻이다. → 부분 함수 종속 발생
따라서 테이블을 아래처럼 학생 테이블
과 수강 테이블
로 나누어 정규화한다.
학생 ID | 이름 | 학과코드 | 학과명 |
---|---|---|---|
1 | 홍길동 | CS | 컴퓨터공학과 |
2 | 이순신 | CS | 컴퓨터공학과 |
3 | 강감찬 | EE | 전자공학과 |
학생 ID | 과목 | 교수명 |
---|---|---|
1 | C | 김교수 |
1 | C++ | 김교수 |
2 | C++ | 김교수 |
3 | JAVA | 이교수 |
제 3정규화란 제 2정규화를 진행한 테이블에 대해 이행적 종속을 없애도록 테이블을 분해하는 것이다. 여기서 이행적 종속이라는 것은 A -> B
, B -> C
가 성립 할 때 A -> C
가 성립되는 것을 의미한다. 아래와 같은 규칙을 만족해야 한다.
학생 ID | 이름 | 학과코드 |
---|---|---|
1 | 홍길동 | CS |
2 | 이순신 | CS |
3 | 강감찬 | EE |
학과코드 | 학과명 |
---|---|
CS | 컴퓨터공학과 |
EE | 전자공학과 |
학생 테이블 안에는 학과코드 -> 학과명
이라는 비주요 속성 간의 종속성이 존재한다.
하지만 학생ID -> 학과코드
도 성립하므로 결과적으로 학생ID -> 학과명
이라는 이행적 종속이 발생하게 된다. 이 종속성을 제거하기 위해 학과명
을 별도의 테이블로 분리한다.
BCNF는 3NF보다 더 엄격한 정규형으로, 결정자가 반드시 후보키여야 한다는 제약 조건이 추가된다. BCNF는 다음과 같은 규칙을 만족해야 한다.
과목 | 교수명 | 강의실 |
---|---|---|
C | 김교수 | 101호 |
C++ | 김교수 | 101호 |
JAVA | 이교수 | 202호 |
위 테이블에서 후보키는 과목
이다. 하지만 교수명 -> 강의실
이라는 함수 종속이 존재하고 교수명
은 후보키가 아니기 때문에 BCNF 정규형을 위반하게 된다.
이 문제를 해결하기 위해 아래와 같이 과목 테이블
과 교수 테이블
로 나누어 정규화한다.
과목 | 교수명 |
---|---|
C | 김교수 |
C++ | 김교수 |
JAVA | 이교수 |
교수명 | 강의실 |
---|---|
김교수 | 101호 |
이교수 | 202호 |
제4정규화(4NF)는 다치 종속(Multivalued Dependency)을 제거하는 정규형이다. 여기서 다치 종속은 A ->-> B
라고 표기하고
한 테이블에서 하나의 기본키에 대해 두 개 이상의 독립적인 다중값 속성이 존재할 경우 -> 4NF를 위반한 것이다.
강사ID | 가능한 요일 | 가능한 지역 |
---|---|---|
T1 | 월요일 | 서울 |
T1 | 월요일 | 부산 |
T1 | 수요일 | 서울 |
T1 | 수요일 | 부산 |
강사ID T1
은 월요일, 수요일 각각 가능하며 서울, 부산 각각 가능하다. 즉, 강사ID ->-> 요일
, 강사ID ->-> 지역
두 다치 종속이 독립적으로 존재 -> 다치 종속이 중복 조합을 발생시킴 → 4NF 위반
강사ID | 가능한 요일 |
---|---|
T1 | 월요일 |
T1 | 수요일 |
강사ID | 가능한 지역 |
---|---|
T1 | 서울 |
T1 | 부산 |
이처럼 독립적인 다중값 속성들을 별도 테이블로 분리함으로써 다치 종속을 제거하고 중복을 방지할 수 있다.
제 5정규화는 모든 조인 종속(Join Dependency)이 후보키에 의해서만 결정되도록 하는 정규형이다. 쉽게 말해 정상적인 재조인이 불가능한 경우를 해결하여 정보 손실 없이 원래 테이블을 복원할 수 있도록 한다.
어떤 테이블을 여러 개로 분해했다가 다시 조인했을 때 원래 테이블과 정확히 같아야 한다. 이게 보장되지 않으면 제5정규화를 위반하는 것이다.
제품ID | 부품 | 공급업체 |
---|---|---|
P1 | B1 | S1 |
P1 | B2 | S1 |
P1 | B1 | S2 |
P1 | B2 | S2 |
이 테이블은 "P1
제품은 B1
, B2
부품으로 구성되며 S1
, S2
업체 모두 제공 가능"을 의미한다. 이 데이터를 세 테이블로 나눌 수 있다.
P1
- B1
/ B2
P1
- S1
/ S2
B1
/B2
- S1
/S2
그러나 이들을 다시 조인하면 불필요한 조합까지 생길 수 있어서 5NF 위반 상황 발생한다.
제품ID | 부품 |
---|---|
P1 | B1 |
P1 | B2 |
제품ID | 공급업체 |
---|---|
P1 | S1 |
P1 | S2 |
부품 | 공급업체 |
---|---|
B1 | S1 |
B2 | S2 |
이 세 테이블을 조인했을 때 정확한 조합만 복원되어야 제5정규화를 만족한다. 만약 추가적인 잘못된 조합이 생긴다면 조인 종속이 깨졌다는 의미이며 이는 5NF 위반이다.
실제 DB 설계에서는 다음을 고려하여 정규화를 진행해야 한다.
정규화는 “어디까지 나눌 것인가”에 대한 균형 잡힌 판단이 중요하다.
정규화를 학습하면서 단순히 중복 제거가 아니라 데이터 간의 의미적 관계를 명확히 정의하고 관리하는 것이 핵심이라는 것을 느꼈다. 특히 4NF와 5NF는 단순 함수 종속을 넘어서 다치 종속과 조인 종속까지 고려해야 하기 때문에 실제 데이터가 어떤 상황에서 유효하고 어떤 경우에는 불필요한 정보가 조인으로 생성될 수 있는지까지 생각하게 되었다.
실무에서는 성능과 조인 비용 문제로 5NF까지 정규화를 진행하는 경우는 드물지만 복잡한 도메인일수록 정규화에 대한 이해도가 유지보수성과 확장성에 큰 차이를 만든다는 점을 확실히 깨달았다. 앞으로 DB 설계 시 단순히 정규화 여부를 따지기보다는 데이터 간 관계, 의미, 변경 가능성까지 고려하여 구조를 잡아나가야겠다.
참고