SQL 기초: 정규화(Normalization) |        Serendipity                                                                                                                                                                                                                                                                                                                                                                                   
Post

SQL 기초: 정규화(Normalization)

🔵 DB를 구축하는 과정에서 이상(Anomlay)을 제거하기 위한 정규화(Normalization)에 대해 알아보았다.

SQL 기초: 정규화(Normalization)

🔵 Intro: 정규화를 도대체 왜 하는가? (The Why)

“데이터 중복”을 줄여서 “이상 현상(Anomaly)”을 막으려고 한다.

만약 정규화가 안 된 ‘나쁜’ 테이블이 있으면:

  1. 삽입 이상 (Insertion Anomaly):
    • 상황: “새 과목으로 ‘AI특강’을 개설하고 싶은데, 아직 신청한 학생이 0명.”
    • 문제: 학생 테이블에 과목 정보를 같이 넣으면, 학생(기본키) 없이는 과목 정보(AI특강)를 삽입조차 못 함.
  2. 갱신 이상 (Update Anomaly):
    • 상황: “A 교수의 사무실이 501호에서 601호로 바뀌었음.”
    • 문제: A 교수의 과목을 듣는 학생이 100명이라면, 100개의 행(row)에 있는 ‘501호’를 전부 ‘601호’로 갱신(Update)해야 함. 하나라도 빼먹으면 데이터가 꼬임. (중복 때문!)
  3. 삭제 이상 (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 위반): 기본키 = {학번, 과목코드}
학번과목코드이름학점
100C001수현A+
100C002수현B+
200C001크리스A0
  • 함수 종속성 분석:
    • {학번, 과목코드} → {학점} (OK: 키 전체에 종속)
    • {학번} → {이름} (🚨 문제! 키의 일부인 ‘학번’만 알아도 ‘이름’이 결정됨 = 부분 종속)
  • [After] (2NF 만족): (부분 종속인 놈들을 떼어내서 별도 테이블로!)
    • [수강 테이블]
    학번과목코드학점
    100C001A+
    100C002B+
    200C001A0
    • [학생 테이블]
    학번이름
    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.