나는 프로젝트를 진행할 때마다 DB 설계가 가장 큰 고민이 된다. 어떻게 설계해야 효율적이고, 나중에 문제가 발생하지 않도록 미리 고려할 수 있을지 항상 어려움을 느낀다. 무엇보다 DB 설계가 제대로 이루어지지 않으면 개발 방향이 엉뚱하게 흘러가거나, 나중에 수정해야 하는 번거로움이 생길 수 있다는 점에서 설계의 중요성을 크게 실감하고 있다.
정규화란?
중복 데이터를 줄이고, 데이터 무결성(Data Integrity)을 보장하기 위해 테이블을 설계하는 과정이다. 이를 통해 데이터 이상 현상(Anomalies)을 방지하고, 효율적인 데이터 관리 및 업데이트를 가능하게 만든다.
정규화의 필요성
- 데이터 중복: 동일한 데이터가 여러 곳에 저장되어 저장 공간 낭비
- 데이터 불일치: 여러 곳에 저장된 데이터 중 일부만 수정되었을 때 데이터 무결성이 깨짐
- 데이터 삽입/삭제/갱신 이상:
- 삽입 이상: 특정 데이터를 추가하려면 불필요한 데이터도 추가해야 함
- 삭제 이상: 데이터를 삭제하면 필요 없는 데이터도 함께 사라질 수 있음
- 갱신 이상: 데이터 수정 시 모든 중복 데이터를 수정해야 함
정규화의 단계
정규화는 1NF부터 시작해 BCNF 및 5NF까지 단계별로 나아가며, 각 단계는 이전 단계를 만족해야 한다.
실무에서는 보통 3NF 또는 BCNF까지만 수행한다고 한다.
정규화 과정과 사용 예시
비정규화 된 데이터부터 정규화가 이루어지는 과정을 살펴보면 이렇다.
비정규화 된 데이터
학생ID | 학생명 | 과목1 | 과목1 교수 | 과목2 | 과목2 교수 |
1 | 유재석 | 수학 | 김교수 | 영어 | 이교수 |
2 | 강호동 | 수학 | 김교수 | 과학 | 박교수 |
3 | 이효리 | 영어 | 이교수 | 과학 | 박교수 |
위 데이터를 보면 여러가지 문제점이 있다.
1. 데이터 중복: 교수 이름이 여러번 반복됨
2. 비원자적 값: 과목이 열 단위로 나뉘어 있음(과목1, 과목2)
3. 삽입 이상: 새로운 학생이 아직 수강하지 않은 경우에도 과목1, 과목2를 비워둬야 함
4. 삭제 이상: 유재석의 데이터를 삭제하면 김교수와 이교수 정보도 함께 사라짐
제 1 정규형 (1NF)
1NF 조건: 각 열은 원자값(Atomic Value)만 가져야 한다. 즉, 하나의 셀에 하나의 값만 있어야 한다는 의미다.
변환 후 데이터
학생ID | 학생명 | 과목 | 교수명 |
1 | 유재석 | 수학 | 김교수 |
1 | 유재석 | 영어 | 이교수 |
2 | 강호동 | 수학 | 김교수 |
2 | 강호동 | 과학 | 박교수 |
3 | 이효리 | 영어 | 이교수 |
3 | 이효리 | 과학 | 박교수 |
- 과목1과 과목2를 각각 행으로 분리
- 하나의 셀에 하나의 값만 들어가도록 수정
제 2 정규형 (2NF)
2NF 조건
1. 1NF를 만족해야 한다.
2. 부분 함수 종속 제거: 기본키(학생ID, 과목) 외 다른 속성(학생명, 교수명)은 기본 키 전체에 종속되어야 한다.
1NF의 문제점
- 학생명은 학생ID에만 종속(부분 함수 종속)
- 교수명은 과목에만 종속(부분 함수 종속)
변환 후 데이터
1. 학생 테이블
학생ID | 학생명 |
1 | 유재석 |
2 | 강호동 |
3 | 이효리 |
2. 과목 테이블
과목 | 교수명 |
수학 | 김교수 |
영어 | 이교수 |
과학 | 박교수 |
3. 수강 테이블
학생ID | 과목 |
1 | 수학 |
1 | 영어 |
2 | 수학 |
2 | 과학 |
3 | 영어 |
3 | 과학 |
변화
- 학생명을 학생 테이블로 분리
- 교수명을 과목 테이블로 분리
- 학생ID와 과목만 남긴 수강 테이블 생성
제 3 정규형(3NF)
3NF 조건
1. 2NF를 만족해야 한다.
2. 이행 함수 종속 제거: 비프라이머리 속성끼리 종속 관계가 없어야 한다.
2NF의 문제점
- 교수명이 과목에 종속 됨
변환 후 데이터
1. 학생 테이블
학생ID | 학생명 |
1 | 유재석 |
2 | 강호동 |
3 | 이효리 |
2. 과목 테이블
과목 | 교수ID |
수학 | 1 |
영어 | 2 |
과학 | 3 |
3. 교수 테이블
교수ID | 교수명 |
1 | 김교수 |
2 | 이교수 |
3 | 박교수 |
4. 수강 테이블
학생ID | 과목 |
1 | 수학 |
1 | 영어 |
2 | 수학 |
2 | 과학 |
3 | 영어 |
3 | 과학 |
변화
- 교수명을 분리하여 새로운 교수 테이블 생성
- 과목 테이블에서 교수ID로 참조
최종 정규화된 데이터
정규화 과정을 거친 후, 데이터 베이스는 아래와 같은 구조를 갖는다.
1. 학생 테이블: 학생 정보를 저장
2. 과목 테이블: 과목별 교수ID를 저장
3. 교수 테이블: 교수의 상세 정보를 저장
4. 수강 테이블: 학생과 과목 간의 관계를 저장
비정규화된 데이터와 비교하면 이렇다.
비정규화 상태
- 하나의 테이블에 모든 데이터를 저장
- 데이터 중복으로 인해 저장 공간 낭비
- 수정 및 삭제 시 이상 현상이 발생
정규화 상태
- 데이터를 논리적으로 분리하여 중복 제거
- 데이터 무결성이 보장되며, 이상 현상이 발생하지 않음
결국 이렇게 정규화 과정을 거치면 정규화의 필요성을 충족시켜준다.
정규화의 장점
1. 데이터 중복이 완전히 제거되어 저장 공간 절약
2. 삽입/삭제/갱신 이상 문제 해결
3. 데이터 무결성 유지가 용이
하지만 무조건 정규화가 좋은점만 있는것은 아니다. 테이블이 여러개로 나뉘어지기 때문이다.
정규화의 단점
- 쿼리 복잡도 증가
- 데이터를 분리하여 저장하므로, 필요한 정보를 조회할 때 여러 테이블을 조인해야 할 수 있다.
- 이는 시스템 성능에 영향을 줄 수 있다.
- 과도한 정규화
- 불필요하게 높은 정규화를 적용하면 데이터베이스 설계가 지나치게 복잡해지고, 유지보수가 어려워질 수 있다.
- 실무에서는 3NF 또는 BCNF까지만 적용하는 경우가 많다.
만약 3NF에서 BCNF로 더 정규화를 진행한다면 이렇게 된다.
3NF에서의 문제점
- 3NF는 학생ID, 과목, 교수 정보를 분리했지만, 교수ID와 과목 사이의 종속 관계가 여전히 남아 있다.
결정자와 종속성
- 과목 → 교수ID가 성립한다.
- 하지만 과목은 후보 키가 아니다.
- 이로 인해, 과목과 교수ID의 종속 관계로 데이터 중복이 발생할 가능성이 있다.
BCNF는 모든 결정자가 후보 키가 되도록 데이터베이스를 다시 설계한다.
여기서 과목 → 교수ID가 문제이므로, 과목-교수 관계를 별도의 테이블로 분리해야 한다.
1. 학생 테이블
학생ID | 학생명 |
1 | 유재석 |
2 | 강호동 |
3 | 이효리 |
2. 수강 테이블
학생ID | 과목 |
1 | 수학 |
1 | 영어 |
2 | 수학 |
2 | 과학 |
3 | 영어 |
3 | 과학 |
3. 과목 - 교수 테이블
과목 | 교수ID |
수학 | 1 |
영어 | 2 |
과학 | 3 |
4. 교수 테이블
교수ID | 교수명 |
1 | 김교수 |
2 | 이교수 |
3 | 박교수 |
BCNF의 특징
- 과목 → 교수ID 관계를 별도의 테이블로 분리하여 과목이 후보 키가 되도록 설계
- 데이터 중복 제거
- 과목-교수 관계가 한 곳에서만 관리된다.
- 예: 수학의 담당 교수(김교수) 정보는 과목-교수 테이블에 한 번만 기록
- 모든 결정자가 후보 키가 되었으므로 BCNF를 만족
3NF vs BCNF 비교
특징 | 3NF | BCNF |
결정자 | 일부 결정자가 후보 키가 아닐 수 있음 | 모든 결정자가 후보 키가 됨 |
데이터 중복 | 일부 중복이 남아 있을 수 있음 | 중복이 완전히 제거됨 |
테이블 수 | 테이블 수가 상대적으로 적음 | 추가적으로 테이블이 생성됨 |
복잡성 | 상대적으로 단순 | 설계가 조금 더 복잡 |
'DB' 카테고리의 다른 글
[DB] Redis란? 개념부터 자료 구조까지 한 번에 정리! (0) | 2025.02.18 |
---|---|
[DB] MongoDB Atlas 설정 및 삭제 방법 총정리 (0) | 2025.02.14 |
[DB] ORM(Object-Relational Mapping)이란? (0) | 2025.02.12 |
[DB] ERD 관계 / 식별자 관계 / 1:1 & 1:N & N:M (0) | 2025.01.16 |