📘 정규화 단계 정리
1. 개요
데이터베이스 설계를 하다 보면, 모든 정보를 한 테이블에 넣고 싶어질 때가 있어요. 그런데 그렇게 만들면 어떤 문제가 생길까요?
- 데이터가 중복되고
- 수정할 때 실수하고
- 삭제했더니 같이 날아가고 😵
이런 문제를 막기 위해 등장한 게 바로 정규화(Normalization) 입니다.
정규화는 테이블을 잘게 나누고, 각 속성을 적절한 자리에 배치해서 데이터의 무결성과 유지보수성을 높이는 설계 방식입니다.
정규화를 하면 단순히 중복만 줄이는 게 아니라,
- 데이터 일관성(consistency) 유지
- 삽입/삭제/수정 이상(Anomaly) 방지
- 테이블 구조가 더 확장성 있게 설계됨
같은 이점이 있습니다.
📖 참고: 이 글은 『이것이 취업을 위한 컴퓨터 과학이다』 CHAPTER 06, p.593 ~ p.604의 내용을 기반으로 한 설명입니다.
2. 정규화 핵심 용어 쉽게 풀어보기
용어 | 쉽게 설명하면… |
---|---|
함수 종속 (A → B) | 하나를 알면 다른 게 자동으로 결정돼요. (예: 학번 → 이름) |
부분 함수 종속 | 키가 여러 개인데, 그 중 일부에만 종속됨 (예: 학번+과목이 키인데 이름은 학번만으로도 알 수 있음) |
이행 함수 종속 | 중간 단계를 거쳐 종속됨 (예: 과목 → 교수 → 사무실) |
후보 키 | 기본키로 쓸 수 있는 후보들 (예: 주민번호, 이메일 등) |
결정자 | 다른 값을 결정짓는 열 (예: 학번이 이름의 결정자) |
3. 제1정규형 (1NF) - 원자값으로만 구성하기
📚 책 용어
제1정규형이란, 모든 속성이 원자값(Atomic Value) 만 가지도록 구성한 테이블입니다.
🧠 쉽게 말하면
하나의 칸에 값이 두 개 이상 들어가면 안 된다는 뜻이에요!
❗ 문제 예시
학번 | 이름 | 수강 과목 | 담당 교수 |
---|---|---|---|
1 | 김현수 | 운영체제, 데이터베이스 | 김교수, 이교수 |
✅ 해결 후 (1NF)
학번 | 이름 | 수강 과목 | 담당 교수 |
---|---|---|---|
1 | 김현수 | 운영체제 | 김교수 |
1 | 김현수 | 데이터베이스 | 이교수 |
4. 제2정규형 (2NF) - 부분 함수 종속 제거
📚 책 용어
제2정규형은 제1정규형을 만족하고, 기본키의 일부에만 종속된 속성이 없어야 합니다.
🧠 쉽게 말하면
키의 ‘일부’만 알아도 값이 정해지는 관계라서 ‘부분’ 종속이라고 불러요.
테이블의 기본키가 두 개일 때, 그 중 하나만 알아도 알 수 있는 값은 따로 빼줘야 합니다.
❗ 문제 예시
학번 | 이름 | 과목 | 성적 |
---|---|---|---|
1001 | 김현수 | 국어 | 90 |
여기서 (학번 + 과목)이 기본키인데, 이름은 학번만으로도 알 수 있죠. 이게 바로 부분 함수 종속입니다.
✅ 해결 후
학생 테이블
학번 | 이름 |
---|---|
1001 | 김현수 |
수강 테이블
학번 | 과목 | 성적 |
---|---|---|
1001 | 국어 | 90 |
5. 제3정규형 (3NF) - 이행 함수 종속 제거
📚 책 용어
제3정규형은 제2정규형을 만족하고, 이행 함수 종속이 없어야 합니다.
🧠 쉽게 말하면
직접 연결된 게 아니라 ‘중간 단계를 거쳐서’ 값이 정해지니까 ‘이행(거쳐가는)’ 종속이에요.
어떤 값을 알면 → 다른 값을 알고 → 또 다른 값을 알 수 있다면?
중간 단계를 거친 종속은 제거해야 합니다.
❗ 문제 예시
과목 | 교수 | 교수 사무실 |
---|---|---|
운영체제 | 김교수 | 3층 301호 |
과목 → 교수 → 사무실 → 이행 함수 종속 발생!
여기서 과목만 알아도 교수, 교수만 알아도 사무실을 알 수 있으니
과목 → 사무실이라는 이행 종속이 생깁니다.
✅ 해결 후
과목-교수 테이블
과목 | 교수 |
---|---|
운영체제 | 김교수 |
교수 테이블
교수 | 사무실 위치 |
---|---|
김교수 | 3층 301호 |
6. 보이스/코드 정규형 (BCNF) - 결정자 조건 추가
사실 이름만 보면 뭔가 어려워 보이는데, 알고 보면 단순합니다.
Boyce-Codd Normal Form은 그냥… “보이스(Boyce)와 코드(Codd)라는 두 사람 이름을 딴 정규형”입니다;;
두 사람이 3NF로는 해결되지 않는 데이터 종속 문제를 발견하고, 이를 해결하기 위해 만든 정규화 기준입니다.
BCNF는 “모든 결정자가 후보 키여야 한다”는 조건을 추가한 제3정규형의 강화 버전입니다. 제3정규형은 시험 볼 때 “틀린 것만 안 쓰면 된다” 수준이라면, BCNF는 “맞춘 것까지 모두 정답인지 증명해야 한다” 수준이라고 보면 됩니다.
“3NF로도 막지 못하는 특이한 종속 케이스를 더 강하게 필터링한 거”입니다.
📚 책 용어
BCNF는 모든 결정자가 후보 키여야 합니다.
🧠 쉽게 말하면
어떤 값을 기준으로 다른 값을 정한다면, 그 기준이 기본키로 쓸 수 있는 값이어야 해요.
후보 키(Candidate Key)는 테이블에서 각 행을 유일하게 식별할 수 있는 모든 열 또는 열 조합을 말해요.
이 중에서 하나를 골라 실제로 테이블의 식별자로 사용하는 것이 바로 기본 키(Primary Key)입니다.
즉, 모든 기본 키는 후보 키지만, 모든 후보 키가 기본 키인 건 아니에요!
예를 들어 주민번호, 이메일, 학번이 모두 유일하다면 셋 다 후보 키이고,
이 중 하나만 기본 키로 선택해서 사용합니다.
💡 모든 후보 키는 결정자다. 하지만 모든 결정자가 후보 키인 것은 아니다.
그래서 BCNF에서는 “모든 결정자는 후보 키여야 한다”는 조건을 추가로 요구합니다.
- 결정자(Determinant):
어떤 속성 A가 다른 속성 B를 결정짓는다면, A는 B의 결정자
👉 예: 학번 → 이름이면, 학번은 이름의 결정자. - 후보 키(Candidate Key):
테이블에서 튜플(행)을 유일하게 구분할 수 있는 속성 또는 속성 집합
👉 후보 키는 무조건 테이블의 다른 모든 속성을 결정할 수 있어요 → 즉, 항상 결정자
하지만!
- 어떤 결정자는 후보 키가 아닐 수도 있어요.
👉 예를 들어 과목 코드 → 교수인 경우, 과목 코드는 교수는 결정하지만 학생을 구분하지는 못하니까 후보 키는 아니죠.
✅ 후보 키는 다 결정자다. 근데 결정자라고 해서 다 후보 키인 건 아니다.
┌────────────────────┐
│ 결정자(D) │ ← 가장 큼 (값을 '결정'한다? 전부 포함)
│ ┌──────────────┐ │
│ │ 후보 키(CK) │ ← 테이블의 행을 유일하게 식별할 수 있는 키들
│ │ ┌──────────┐│ │
│ │ │ 기본 키(PK) │ ← 후보 키 중에서 선택된 단 하나의 키
│ │ └──────────┘│ │
│ └──────────────┘ │
└────────────────────┘
기본 키 ⊂ 후보 키 ⊂ 결정자
(선택된 키 ⊂ 유일한 키들 ⊂ 뭔가를 결정할 수 있는 애들)
❗ 문제 예시
학번 | 과목 코드 | 담당 교수 |
---|---|---|
1 | CS101 | 김교수 |
여기서 과목 코드가 교수님을 정하지만, 과목 코드 자체는 기본키가 아니에요.
과목 코드 → 담당 교수인데, 과목 코드가 후보 키가 아니라면 BCNF 위반입니다.
✅ 해결 후
과목 테이블
과목 코드 | 담당 교수 |
---|---|
CS101 | 김교수 |
학생-과목 테이블
학번 | 과목 코드 |
---|---|
1 | CS101 |
7. ERD로 보는 정규화 예시
📎 ERD 예시
[비정규형 (UNF)]
학번, 이름, 수강 과목(복수), 교수(복수)
↓ 원자값 분해
[1NF]
학번, 이름, 과목, 교수
↓ 부분 종속 제거
[2NF]
학생(학번, 이름)
수강(학번, 과목, 성적)
↓ 이행 종속 제거
[3NF]
과목(과목, 교수)
교수(교수, 사무실)
↓ 모든 결정자 → 후보 키
[BCNF]
과목(과목 코드, 교수 코드)
교수(교수 코드, 사무실)
학생이 수강한 과목과 교수 정보를 1NF → BCNF까지 정규화한 결과입니다.
• 교수 이름이 바뀌면 → 과목과의 관계가 모두 깨질 수 있음
• 교수명이 유일하다는 보장도 없음 (김민수 교수 3명 있을 수 있음)
• 데이터 무결성 깨질 위험 + 변경 이상 발생
틀린 그림 찾기가 아니라 '과목코드' '교수코드'가 추가됨.
처음에는 하나의 테이블에 모든 정보가 들어 있었지만,
정규화 과정에서 학생, 수강, 과목, 교수로 분리되었고,
각 테이블은 외래키(FK)를 통해 관계를 맺고 있습니다.
BCNF에서는 “모든 결정자는 반드시 후보 키여야 한다”는 조건이 적용됩니다.
예를 들어 과목명이 교수님을 결정짓는다면, 과목명은 반드시 후보 키여야 해요.
이를 위해 ‘과목 코드’와 ‘교수 코드’ 같은 식별 가능한 속성으로 테이블을 재설계하게 됩니다.
🧩 여기서 잠깐! 식별 관계 vs 비식별 관계
ERD를 설계할 때, 테이블 간 연결 관계는 식별 관계와 비식별 관계로 나뉩니다.
두 개념은 외래키가 기본키에 포함되는지 여부에 따라 구분돼요.
구분 | 의미 | 외래키 특징 | 예시 |
식별 관계 (Identifying) |
부모 없이는 자식도 존재할 수 없음 | 외래키가 기본키에 포함됨 | 주문 → 주문 상세 |
비식별 관계 (Non-identifying) |
부모 없어도 자식은 독립적으로 존재 가능 | 외래키는 일반 속성 (기본키 아님) |
사용자 → 게시글 |
- 식별 관계: “부모 없으면 나도 없어” → FK가 PK 안에 들어감
- 비식별 관계: “부모 없어도 난 있어” → FK는 그냥 참조용
ㄴ “외래키는 일반 속성”이란? 비식별 관계에서는 외래키가 자식 테이블의 기본키에 포함되지 않는다 : 외래키는 그냥 “참조용”일 뿐이고, 그 자체가 이 테이블에서 행을 식별하는 기본키 역할을 하지는 않음
📘 예를 들어
- `주문 상세`는 해당 주문이 반드시 있어야만 존재할 수 있어요 → 식별 관계
- `게시글`은 작성한 사용자가 탈퇴해도 게시글 자체는 남길 수 있어요 → 비식별 관계
식별 관계는 부모 테이블이 삭제되면 자식 테이블도 함께 사라질 수 있는 구조로,
생명선을 공유하며 논리적으로 완전 종속된 관계입니다.
반면, 비식별 관계는 실무에서 더 자주 사용되며,
데이터 삭제나 수정 시에도 유지보수가 유연하고 독립성이 보장되는 장점이 있습니다.
8. 정규화 흐름도 요약
💬 참고: 비정규형(UNF) 이란?
- 한 셀에 여러 개의 값이 들어 있는 상태 (예: 전화번호: "010-1111-2222, 010-3333-4444")
- 정규화를 하기 전의 '지저분한 테이블' 상태예요.
→ 1NF부터는 이걸 원자값으로 분해합니다.
요약
- 1NF: 칸칸이 정리하자 (엑셀 한 셀에 값 하나씩)
- 2NF: 덜 중요한 건 따로 떼자 (부분 종속 분리)
- 3NF: 간접적인 연결은 없애자 (이행 종속 제거)
- BCNF: 모든 기준이 진짜 고유해야 한다 (결정자 = 후보 키)
9. 역정규화는 언제 쓸까?
📌 정규화에도 단점이 있다
- 테이블이 지나치게 분리되어 JOIN이 많아지고 성능이 저하될 수 있어요
- 너무 많은 정규형을 적용하면 데이터 구조가 복잡해져 개발자/쿼리 작성자 모두 힘들 수 있습니다
→ 그래서 실무에서는 '정규화 vs 역정규화'를 적절히 조절하는 게 핵심입니다.
즉, 정규화가 항상 좋은 건 아닙니다. 아래와 같은 경우에는 역정규화가 필요할 수 있어요.
- JOIN이 너무 많아서 조회 성능이 떨어지는 경우
- 분석/리포트 시스템처럼 빠른 읽기가 중요한 경우
- NoSQL 환경에서는 기본적으로 정규화를 하지 않기도 해요
이럴 땐 의도적으로 중복을 허용하고, 테이블을 통합하기도 합니다.
🔚 마무리
실무에서는 항상 BCNF까지 정규화를 할 필요는 없어요.
데이터 무결성이 중요한 테이블은 정규화하고,
조회 성능이 중요한 테이블은 역정규화하는 식의
균형감 있는 설계가 중요합니다.
정규화는 단순히 테이블을 쪼개는 게 아니라,
왜 쪼개야 하는지, 어떤 문제가 생기기 때문인지를 이해하는 게 핵심입니다.
참고자료
'Database' 카테고리의 다른 글
샤딩 vs 파티셔닝, 무엇을 언제 선택해야 할까? – 데이터 분산 전략 (0) | 2025.04.09 |
---|---|
NoSQL의 모든 것: 개념, 종류, MongoDB와 Redis 맛보기 (0) | 2025.04.08 |
효율적 쿼리란? - 서브쿼리와 조인, 뷰, 인덱스로 쿼리 최적화 (0) | 2025.04.07 |
웹 개발자라면 꼭 알아야 할 데이터베이스 기초 정리 (0) | 2025.04.07 |
데이터베이스 트랜잭션 ACID 특성과 BASE 데이터 일관성 모델 (3) | 2025.02.27 |