정규화(Normalization) 는 데이터베이스 설계에서 데이터를 구조화하여 데이터 중복을 최소화하고, 데이터 무결성을 유지하며, 데이터베이스 성능을 최적화하는 과정이다. 정규화는 여러 단계로 나누어지며, 각 단계는 특정한 정규형을 만족시키도록 데이터베이스를 변환한다.
정규화(Normalization) 목적
1. 데이터 중복 최소화
데이터 중복을 줄여 저장 공간을 효율적으로 사용하고, 데이터 일관성을 유지한다.
2. 데이터 무결성 유지
데이터 무결성을 유지하여 데이터의 정확성과 신뢰성을 보장한다.
3. 데이터베이스 성능 최적화
효율적인 데이터베이스 구조를 통해 쿼리 성능을 향상시킨다.
정규화(Normalization) 과정
1. 제1정규형 (1NF: First Normal Form)
모든 열의 값이 원자 값(atomic value) 이어야 한다. 즉, 각 컬럼에 하나의 값만 있어야 한다.
비정규화 테이블
ID | 이름 | 사는곳 |
1 | 철수 | 서울, 경기 |
2 | 영희 | 전주 |
1NF 변환
ID | 이름 | 사는곳 |
1 | 철수 | 서울 |
2 | 철수 | 경기 |
3 | 영희 | 전주 |
2. 제2정규형(2NF: Second Normal Form)
1NF 를 만족하고, 기본키의 부분 집합이 비기본 속성에 함수적 종속성을 가지지 않아야 한다.
즉, 부분 종속성을 제거해야 한다.
부분 종속성이란?
기본 키의 일부가 비기본 속성을 결정하는 것이다. 예를 들어, 테이블의 기본 키가 A,B 일때 A 만으로 비기본 속성 C 를 결정할 수 있다면 A 에 부분 종속성을 가진다고 한다.
아래 예시를 보자.
비정규화 테이블 (1NF 만족)
학생ID | 과목 | 교수 |
1 | 수학 | 김교수 |
1 | 영어 | 이교수 |
2 | 수학 | 김교수 |
2 | 과학 | 박교수 |
위 테이블의 기본 키는 학생ID, 과목 컬럼이다.
교수 컬럼은 과목 컬럼에 의해 결정이 되는 컬럼이다. 즉, 교수 컬럼은 기본 키인 학생ID, 과목 컬럼에 모두 종속되는 것이 아니라 과목이라는 하나의 컬럼에만 종속이 되는 것이다.
이것을 부분 종속성이라고 한다.
그렇다면 부분 종속성이 왜 문제가 되냐?
여기에서 '박교수' 라는 수학을 담당하는 교수 컬럼의 데이터가 두 번 저장되어 있다. (데이터 중복 발생)
또, 수학을 담당하는 교수가 '박교수' 에서 '장교수' 로 변경이 되었다고 하자.
그렇다면 위 테이블에서 관련 행이 두개가 있어 두개의 행을 업데이트 해야하며, 만약 하나의 행만 업데이트하고 나머지를 업데이트 하지 않으면 데이터가 일관되지 않게 된다. (데이터 무결성 깨짐)
만약, 국어를 담당하는 '강교수' 가 채용되었다고 하자. 하지만, 아직 국어를 듣는 학생은 없다.
이의 경우, 아래와 같이 불필요한 학생ID 를 추가하는 이상 데이터를 삽입할 수도 있게된다.
학생ID | 과목 | 교수 |
NULL | 국어 | 강교수 |
이와 같이 부분 종속성이 존재하면 데이터베이스에서 데이터 중복, 데이터 무결성 문제, 이상 데이터 삽입 등 문제가 발생할 수 있다. 이러한 문제를 방지하기 위해 2NF 로 변환이 필요하다.
아래 2NF 로 변환한 예시를 보자.
학생/과목 테이블
학생ID | 과목 |
1 | 수학 |
1 | 영어 |
2 | 수학 |
2 | 과학 |
과목/교수 테이블
과목 | 교수 |
수학 | 김교수 |
영어 | 이교수 |
과학 | 박교수 |
위와 같이 테이블을 분리하므로써, 각각의 테이블은 2NF 를 만족하게 된다.
과목 컬럼으로 인한 교수 컬럼의 중복 데이터는 존재하지 않게 되며, 교수 컬럼의 변경으로 인한 업데이트는 1회만 발생이 가능하게 된다.
3. 제3정규형 (3NF: Third Normal Form)
2NF 를 만족하고, 비기본 속성이 다른 비기본 속성에 이행적 함수 종속성을 가지지 않아야 한다.
이행적 함수 종속성이란?
이행적 함수 종속성은 기본 키가 아닌 비기본 속성이 다른 비기본 속성에 종속될 때 발생한다.
즉, A -> B 이고 B -> C 일 때 A -> C 라는 종속성을 말한다.
아래 예시를 보자.
비정규화 테이블 (2NF 만족)
학생ID | 학생명 | 학과ID | 학과명 |
1 | 철수 | 101 | 컴퓨터공학 |
2 | 영희 | 102 | 정보통신과 |
3 | 민수 | 101 | 컴퓨터공학 |
이 테이블에서의 기본 키는 학생ID 이다.
여기에서 학생ID 로 학과ID 를 알 수 있으며, 학과ID 는 학과명 을 알 수 있다.
이처럼 학생ID → 학과ID 이고 학과ID → 학과명 일 때 학생ID → 학과명 이라는 이행적 종속성을 갖게 되는 것이다.
이 또한 동일한 데이터가 여러 곳에 중복 저장되는 데이터 중복이 발생할 수 있으며, 데이터 무결성 문제가 발생할 수 있다.
이러한 문제를 방지하기 위해 3NF 로 변환이 필요하다.
3NF 로 변환해보자.
학생 테이블
학생ID | 학생명 | 학과ID |
1 | 철수 | 101 |
2 | 영희 | 102 |
3 | 민수 | 101 |
학과 테이블
학과ID | 학과명 |
101 | 컴퓨터공학 |
102 | 정보통신과 |
이렇게 분리하면 학생ID 는 더 이상 학과명 에 이행적 종속성을 가지지 않게 된다.
4. 보이스-코드 정규형(BCNF: Boyce-Codd Normal Form)
3NF 보다 엄격하게 적용한 정규형이다. 모든 결정자가 후보 키여야 하는 조건을 추가로 요구한다.
결정자(Determinant) 란?
테이블에서 다른 컬럼의 값을 고유하게 결정할 수 있는 속성 또는 속성의 집합이다.
후보키(Candidate Key) 란?
테이블의 모든 행을 고유하게 식별할 수 있는 최소 속성의 집합이다. 하나의 테이블에는 여러 후보 키가 있을 수 있으며, 후보 키 중에서 기본 키(Primary Key) 가 선택된다.
제3정규형을 만족하는 테이블이라도 모든 결정자가 후보 키가 아닐 수 있는 경우에는 여전히 데이터 중복과 무결성 문제가 발생할 수 있다. 이러한 경우, BCNF 로 변호나하여 문제를 해결할 수 있다.
예시를 보자.
비정규화 테이블 (3NF 만족)
강의ID | 교수명 | 강의시간 | 강의실 |
101 | 김교수 | 09:00 | A |
102 | 이교수 | 10:00 | B |
103 | 김교수 | 11:00 | A |
104 | 박교수 | 12:00 | C |
이 테이블에서 결정자와 후보키는 아래와 같을 것이다.
*결정자: 교수명, 강의시간 (강의실을 결정함)
*후보키: 강의ID (모든 행을 고유하게 식별)
BCNF 를 만족시키려면 모든 결정자가 후보키가 되어야한다고 했다.
하지만 이 테이블에서 교수명, 강의시간은 모든 행을 고유하게 식별하는 후보키가 아니다.
고로, BCNF 를 만족시키기 위해 결정자(교수명, 강의시간) 이 후보 키가 되도록 테이블을 아래와 같이 분리해야한다.
강의 테이블
강의ID | 교수명 | 강의시간 |
101 | 김교수 | 09:00 |
102 | 이교수 | 10:00 |
103 | 김교수 | 11:00 |
104 | 박교수 | 12:00 |
*후보 키: 강의ID
교수시간표 테이블
교수명 | 강의시간 | 강의실 |
김교수 | 09:00 | A |
김교수 | 11:00 | A |
이교수 | 10:00 | B |
박교수 | 12:00 | C |
*결정자: 교수이름, 강의시간
*후보 키: 교수이름, 강의시간
위와 같이 BCNF 를 만족시키기 위해 모든 결정자가 후보 키가 되도록 테이블을 분리한다. 이렇게 하면 데이터 중복과 무결성 문제를 방지할 수 있다.
5. 제4정규형 (4NF: Fourth Normal Form)
3NF 를 만족하며, 다치 종속성을 제거해야한다.
다치 종속성(Multivalued Dependency) 이란?
다중 값 속성들 간의 관계로 인해 발생하는 종속성이다.
고객ID | 고객명 | 취미 | 연락처 |
1 | 철수 | 노래 | 01012345678 |
1 | 철수 | 춤 | 021234567 |
1 | 철수 | 운동 | 01012345678 |
2 | 영희 | 독서 | 0119876543 |
2 | 영희 | 등산 | 0119876543 |
예를 들어, 하나의 고객은 여러 가지의 취미를 가질 수 있고, 연락처 정보를 가질 수 있다.
고객ID 는 취미, 연락처 에 다치 종속성을 갖게 되는 것이다.
여기에서 문제가 무엇이냐면, 철수의 연락처를 변경하면 모든 관련 행을 업데이트해야 하므로 데이터 일관성 유지하기가 어렵다는 점이다. 이처럼 다치 종속성이 존재하면 데이터 무결성 문제가 발생할 수 있다.
다치 종속성을 제거하여 4NF 로 변환해보자.
고객/취미 테이블
고객ID | 고객명 | 취미 |
1 | 철수 | 노래 |
1 | 철수 | 춤 |
2 | 영희 | 독서 |
2 | 영희 | 등산 |
고객/연락처 테이블
고객ID | 고객명 | 연락처 |
1 | 철수 | 01012345678 |
1 | 철수 | 021234567 |
2 | 영희 | 0119876543 |
테이블을 분리하므로써 다치 종속성을 제거하여 제 4정규형을 만족하게 된다.
이제 철수의 연락처를 업데이트하면 관련 행 하나만 업데이트 할 수 있어 데이터베이스의 구조를 보다 효율적이고 일관성 있게 유지할 수 있다.
6. 제5정규형 (5NF: Fifth Normal Form)
4NF 를 만족하고, 조인 종속성이 존재하고 이를 통해 원래의 테이블을 복원할 수 있는 경우이다.
조인 종속성(Join Dependency) 란?
데이터베이스의 테이블이 여러 테이블로 분해될 때, 이들 테이블을 다시 조인하여 원래의 테이블을 복원할 수 있는 종속성을 의미한다. 조인 종속성은 특정 관계를 만족하는 세 개 이상의 테이블로 분해된 경우 발생할 수 있다.
비정규화 테이블 (4NF 만족)
직원ID | 프로젝트ID | 공급업체ID |
1 | A | X |
1 | A | Y |
2 | B | Y |
2 | B | Z |
3 | A | X |
3 | C | Z |
위 테이블을 조인 종속성을 적용하여 아래와 같이 분해할 수 있다.
직원-프로젝트 테이블
직원ID | 프로젝트ID |
1 | A |
2 | B |
3 | A |
3 | C |
프로젝트-공급업체 테이블
프로젝트ID | 공급업체ID |
A | X |
A | Y |
B | Y |
B | Z |
C | Z |
직원-공급업체 테이블
직원ID | 공급업체ID |
1 | X |
1 | Y |
2 | Y |
2 | Z |
3 | X |
3 | Z |
분해한 세 가지의 테이블을 조인해보자.
SELECT 직원-프로젝트.직원ID, 프로젝트-공급업체.프로젝트ID, 프로젝트-공급업체.공급업체ID
FROM 직원-프로젝트
JOIN 프로젝트-공급업체 ON 직원-프로젝트.프로젝트ID = 프로젝트-공급업체.프로젝트ID
JOIN 직원-공급업체 ON 직원-프로젝트.직원ID = 직원-공급업체.직원ID AND 프로젝트-공급업체.공급업체ID = 직원-공급업체.공급업체ID;
이 조인 결과는 테이블을 분해하기 전인 원래 테이블과 동일하게 나타난다.
따라서 이 분해 과정은 조인 종속성을 가지고 있으며, 제5정규형을 만족하게 된다.
결론
1NF | 모든 컬럼 값이 원자 값이어야한다. |
2NF | 부분 종속성을 제거한다. |
3NF | 이행적 종속성을 제거한다. |
BCNF | 결정자가 후보 키여야 한다. |
4NF | 다치 종속성을 제거한다. |
5NF | 조인 종속성을 제거한다. |
정규화의 목표는 데이터 무결성과 효율성을 유지하는 것인데 지나친 정규화는 테이블간의 조인이 많아져서 성능 저하를 초래할 수도 있다. 대부분은 3NF 또는 BCNF 까지 정규화를 하며, 일부 복잡한 데이터 모델의 경우 4NF, 5NF 까지 하기도 한다. 따라서, 데이터베이스 설계 시 정규화와 성능 사이의 균형을 맞추는 것이 중요하다.
'Database' 카테고리의 다른 글
[Database] 인덱스 스플릿 (Index Split) (0) | 2024.06.22 |
---|---|
[Database] 인덱스 (클러스터드,넌클러스터드,구조,종류,생성) (1) | 2024.03.05 |
[Database] JOIN 기법의 종류 (Nested Loops Join, Merge Join, Hash Join) (0) | 2024.02.22 |
[Database] 트랜잭션 격리 수준 (Transaction Isolation Level) (0) | 2023.10.23 |
[Database] MVCC - 다중 버전 동시성 제어 (Multi Version Concurrency Control) (2) | 2023.10.18 |