SQL 기초: 정규화(Normalization)
🔵 DB를 구축하는 과정에서 이상(Anomlay)을 제거하기 위한 정규화(Normalization)에 대해 알아보았다.
SQL 기초: 정규화(Normalization)
🔵 Intro: 정규화를 도대체 왜 하는가? (The Why)
“데이터 중복”을 줄여서 “이상 현상(Anomaly)”을 막으려고 한다.
만약 정규화가 안 된 ‘나쁜’ 테이블이 있으면:
- 삽입 이상 (Insertion Anomaly):
- 상황: “새 과목으로 ‘AI특강’을 개설하고 싶은데, 아직 신청한 학생이 0명.”
- 문제: 학생 테이블에 과목 정보를 같이 넣으면, 학생(기본키) 없이는 과목 정보(AI특강)를 삽입조차 못 함.
- 갱신 이상 (Update Anomaly):
- 상황: “A 교수의 사무실이 501호에서 601호로 바뀌었음.”
- 문제: A 교수의 과목을 듣는 학생이 100명이라면, 100개의 행(row)에 있는 ‘501호’를 전부 ‘601호’로 갱신(Update)해야 함. 하나라도 빼먹으면 데이터가 꼬임. (중복 때문!)
- 삭제 이상 (Deletion Anomaly):
- 상황: “학생 ‘수현’이 ‘데이터베이스’ 과목 수강을 취소했음.”
- 문제: 만약 ‘수현’이 그 과목의 마지막 학생이었다면? ‘수현’의 수강 정보를 삭제(Delete)했더니, “데이터베이스 과목” 정보까지 통째로 날아가 버림.
정규화는 바로 이런 ‘이상 현상’들을 막기 위해, 중복을 제거하며 테이블을 잘게 쪼개는 과정이다.
🔵 정규화의 핵심 도구: “함수 종속성 (X → Y)”
정규화를 하려면 “누가 누구를 결정하는가”를 알아야 해.
- X → Y : “X를 알면 Y를 알 수 있다.” (Y는 X에 함수적으로 종속된다)
- 예시: {학번} → {이름, 학과}
- ‘학번’을 알면 ‘이름’과 ‘학과’가 유일하게 결정되지?
- 이때 ‘학번’처럼 다른 모든 걸 결정하는 놈을 ‘결정자’이자 ‘기본키(Primary Key)’라고 부르는 거야.
정규화 단계별 예제 (1NF ~ BCNF)
시험에는 1, 2, 3NF, BCNF가 99% 나와. (4, 5NF는 용어만 알면 돼) 이 순서(1 → 2 → 3 → BCNF)를 “두-부-이-결” (또는 “원-부-이-결”)로 외우면 편해.
⚪ 1NF (제1정규형): “원자값” (Atomic Value)
- 규칙: 테이블의 모든 칸에는 값이 1개만 있어야 한다. (즉, 원자값만 허용)
- [Before] (위반):
| 학번 | 이름 | 수강과목 |
|---|---|---|
| 100 | 수현 | {데이터베이스, 운영체제} |
- [After] (1NF 만족): (한 칸에 하나씩 쪼갬)
| 학번 | 이름 | 수강과목 |
|---|---|---|
| 100 | 수현 | 데이터베이스 |
| 100 | 수현 | 운영체제 |
⚪ 2NF (제2정규형): “부분 함수 종속” 제거
- 규칙: “완전 함수 종속”을 만족해야 한다. (즉, 부분 함수 종속 제거)
- ※ 언제 발생? ‘복합 키’ (키가 2개 이상)일 때만 발생해!
- [Before] (2NF 위반):
기본키 = {학번, 과목코드}
| 학번 | 과목코드 | 이름 | 학점 |
|---|---|---|---|
| 100 | C001 | 수현 | A+ |
| 100 | C002 | 수현 | B+ |
| 200 | C001 | 크리스 | A0 |
- 함수 종속성 분석:
{학번, 과목코드} → {학점}(OK: 키 전체에 종속){학번} → {이름}(🚨 문제! 키의 일부인 ‘학번’만 알아도 ‘이름’이 결정됨 = 부분 종속)
- [After] (2NF 만족): (부분 종속인 놈들을 떼어내서 별도 테이블로!)
- [수강 테이블]
학번 과목코드 학점 100 C001 A+ 100 C002 B+ 200 C001 A0 - [학생 테이블]
학번 이름 100 수현 200 크리스
⚪ 3NF (제3정규형): “이행적 함수 종속” 제거
- 규칙: “이행적 함수 종속”을 제거해야 한다.
- ※ 이행적 종속이란? “꼬리물기” 종속. (A → B 이고 B → C 일 때) 즉, 키가 아닌 일반 컬럼이 다른 일반 컬럼을 결정하는 경우.
- [Before] (3NF 위반):
기본키 = {학번}
| 학번 | 이름 | 학과코드 | 학과명 | 학과전화 |
|---|---|---|---|---|
| 100 | 수현 | CS | 컴퓨터공학과 | 123-4567 |
| 200 | 크리스 | EE | 전기전자공학 | 765-4321 |
- 함수 종속성 분석:
{학번} → {이름, 학과코드}(OK){학과코드} → {학과명, 학과전화}(🚨 문제! 키도 아닌 ‘학과코드’가 다른 컬럼을 결정함 = 이행적 종속)
- [After] (3NF 만족): (꼬리물기 하는 놈들을 떼어내서 별도 테이블로!)
- [학생 테이블]
학번 이름 학과코드 100 수현 CS 200 크리스 EE - [학과 테이블]
학과코드 학과명 학과전화 CS 컴퓨터공학과 123-4567 EE 전기전자공학 765-4321
⚪ BCNF (Boyce-Codd 정규형): “결정자”가 모두 “후보 키”
- 규칙: (3NF보다 강력함) “모든 결정자가 후보 키여야 한다.”
- ※ 언제 발생? ‘후보 키’(기본키가 될 수 있는 놈들)가 여러 개일 때 주로 발생.
- [Before] (BCNF 위반): (가정: 학생은 과목마다 교수를 1명만, 교수는 1과목만 강의)
후보 키 1 = {학번, 과목명}후보 키 2 = {학번, 교수명}
학번 과목명 교수명 100 데이터베이스 김교수 200 운영체제 이교수 200 데이터베이스 김교수 - 함수 종속성 분석:
{학번, 과목명} → {교수명}(OK: 결정자가 후보 키){학번, 교수명} → {과목명}(OK: 결정자가 후보 키){교수명} → {과목명}(🚨 문제! ‘교수명’은 후보 키가 아닌데(키의 일부일 뿐) ‘과목명’을 결정함 = BCNF 위반)
- [After] (BCNF 만족): (결정자인데 후보 키가 아닌 놈을 분리!)
- [수강 테이블]
| 학번 | 교수명 | | :— | :— | | 100 | 김교수 | | 200 | 이교수 | | 200 | 김교수 | * [교수과목 테이블] | 교수명 | 과목명 | | :— | :— | | 김교수 | 데이터베이스 | | 이교수 | 운영체제 |
🔵 시험 대비 최종 요약 (키워드 암기)
이것만 외우자.. “두-부-이-결-다-조”
- 1NF (두/원): 원자값 (한 칸에 하나)
- 2NF (부): 부분 함수 종속 제거 (복합 키일 때 발생)
- 3NF (이): 이행적 함수 종속 제거 (키 아닌 놈이 키 아닌 놈을 결정)
- BCNF (결): 결정자가 모두 후보 키 (3NF 강화)
- 4NF (다): 다치 종속 (Multi-valued Dependency) 제거
- 5NF (조): 조인 종속 (Join Dependency) 제거
This post is licensed under CC BY 4.0 by the author.
