데이터베이스 과정에서 배운 정규화에 대해 정리해 보려 한다. 처음 들었을 때 이해가 안 되는 부분들이 많아 정리하면서 개념을 잡아보려 한다. 👩🏻💻💭
데이터베이스 설계 시 데이터의 중복을 최소화하고, 데이터 일관성과 무결성을 유지하기 위한 테이블 구조화 과정으로, 데이터의 결함을 제거하여 표준화된 형태로 만드는 것이다.
즉, '테이블을 잘 쪼개서 데이터 중복을 없애자!' 라고 생각하면 될 것 같다.
💡 한 셀에 여러 전화번호를 저장하지 않고, 각각 별도의 행으로 분리
❌ Before 1NF
회원ID(1), 이름(민지), 연락처(010-0000-0000, 02-000-0000)
✅ After 1NF
회원ID(1), 이름(민지), 연락처(010-0000-0000)
회원ID(1), 이름(민지), 연락처(02-0000-0000)
[주문] 테이블
(회원ID, 상품ID) -> (주문일자, 수량, 회원연락처, 상품명)
여기서 문제는 회원연락처는 회원ID만으로 결정되고, 상품명은 상품ID만으로 결정된다. 즉, 복합키(회원ID, 상품ID) 전체가 아닌 일부만으로 결정되는 부분적 함수 종속이 발생한다.
☑️ Before 2NF
| 회원ID | 상품ID | 주문일자 | 수량 | 회원연락처 | 상품명 |
|---|---|---|---|---|---|
| 1 | A | 2025.01.01 | 2 | 010-0000-0000 | 아메키라노 |
| 2 | A | 2025.01.02 | 1 | 010-1234-5678 | 아메키라노 |
✅ After 2NF
[회원] 테이블
| 회원ID | 회원연락처 |
|---|---|
| 1 | 010-0000-0000 |
| 2 | 010-1234-5678 |
[상품] 테이블
| 상품ID | 상품명 |
|---|---|
| A | 아메리카노 |
[주문] 테이블
| 회원ID | 상품ID | 주문일자 | 수량 |
|---|---|---|---|
| 1 | A | 2025.01.01 | 2 |
| 2 | A | 2025.01.02 | 1 |
x > y 이고, y > z이면 x > z 이다.
[주문] 테이블
주문ID -> 회원ID -> 회원연락처
주문ID -> 메뉴ID -> 메뉴명
이런 관계에서는 주문ID로 회원ID를 찾고, 회원ID로 회원연락처를 찾는 구조인데 이런 간적접인 참조 관계를 제거해야 한다.
☑️ Before 3NF
| 주문ID | 회원ID | 회원연락처 | 메뉴ID | 메뉴명 |
|---|---|---|---|---|
| 1 | A | 010-0000-0000 | M1 | 아메키라노 |
✅ After 3NF
[회원] 테이블
| 회원ID | 회원연락처 |
|---|---|
| 1 | 010-0000-0000 |
[메뉴] 테이블
| 메뉴ID | 메뉴명 |
|---|---|
| M1 | 아메리카노 |
[주문] 테이블
| 주문ID | 회원ID | 메뉴ID |
|---|---|---|
| 1 | A | M1 |
상황: 학교에서 일정표를 만든다.
일정표(학생이름, 수업이름, 선생님, 교실번호)
📍 3NF
"선생님이 어떤 수업을 가르치는지는 기록해도 괜찮아!"
위의 일정표는 3NF이다. 약간의 반복이 있지만 괜찮다.
📍 BCNF
"아니야, 선생님이 어떤 수업을 가르치는지, 어떤 교실에서 가르치는지는 따로 기록하자!"
수업-선생님표: (수업이름, 선생님)
-수학, 김선생님
-영어, 박선생님
선생님-교실표: (선생님, 교실번호)
-김선생님, 101호
-박선생님, 102호
학생-수업표: (학생이름, 수업이름)
-민지, 수학
-민지, 영어
-리나, 수학
3NF: "일정표 하나로 관리해도 괜찮아!"(약간 중복되더라도)
BCNF: "정보는 딱 한 번만 쓰자. 필요할 때 여러 표를 보면 돼!"
=> 3NF는 약간의 중복을 허용하고, BCNF는 중복을 완전히 없애고 싶어 한다.
학생들이 여러 과목을 수강하는 경우의 문제
☑️ Before 4NF
| 이름 | 과목 |
|---|---|
| 민지 | Javascript |
| 리나 | Javascript |
| 수지 | Javascript |
| 민지 | Reactjs |
| 리나 | Reactjs |
| 수지 | Reactjs |
| 민지 | Nextjs |
| 리나 | Nextjs |
| 수지 | Nextjs |
이 구조는 학생 3명과 과목 3개의 모든 조합(9개)을 저장한다. 이는 다치 중속 문제이다.
✅ After 4NF
[학생] 테이블
| 학생ID | 이름 |
|---|---|
| 1 | 민지 |
| 2 | 리나 |
| 3 | 수지 |
[과목] 테이블
| 과목ID | 과목명 |
|---|---|
| 1 | Javascript |
| 2 | Reactjs |
| 3 | Nextjs |
[수강] 테이블
| 학생ID | 과목ID |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| ... | ... |
배운 내용을 바탕으로 팀원들과 함께 ERD 다이어그램을 그려보았다. 각 정규화 단계별로 어떻게 테이블이 변화하는지 시가적으로 확인할 수 있어서 이해하는 데 도움이 되었다.



정규화 개념이 너무 추상적이고 어렵게 느껴졌는데, 예시와 다이어그램을 통해 차근차근 공부하니 점차 이해가 되어갔던 것 같다. 특히 3NF랑 BCNF를 차이점을 구분하는 게 어려웠는데 팀원들과 이야기 나눠가며 하다 보니 어느 정도 명확해진 것 같다. 앞으로 하게 될 프로젝트에서 데이터베이스를 설계해야 해서 그 과정에 참여를 하게 된다면 이러한 정규화 원칙을 적용하여 더 효율적이고 일관성 있는 시스템을 구축해 보고 싶다.