세 번째 정규형(3NF)은 우리 데이터에 더 질서를 부여하는 단계야. 간단히 말해서, 테이블이 3NF에 있으면:
- 이미 두 번째 정규형(2NF)을 만족하고 있어야 해.
- 모든 비키(비주요) 속성은 오직 기본키에만 의존해야 하고, 다른 것엔 의존하면 안 돼(트랜지티브 의존성은 절대 안 됨!).
즉, 3NF는 테이블의 모든 데이터가 기본키와 직접적으로 연결되어야 하고, 다른 비키 속성에 의존하면 안 된다는 거야.
트랜지티브 의존성은 A 속성이 B에 의존하고, B가 C에 의존할 때 생겨. 그래서 A → B → C 이런 식으로 의존성 체인이 만들어져. 예를 들어, "직원"이 "부서"에 의존하고, "부서"가 "위치"에 의존하면, "직원"은 트랜지티브하게 "위치"에 의존하게 되는 거지.
3NF 위반 예시
예를 들어, employees 테이블이 있다고 해보자. 이 테이블은 직원 정보를 저장해:
| employee_id | name | department | department_manager |
|---|---|---|---|
| 1 | Otto Lin | Marketing | Leo Zhang |
| 2 | Alex Song | Finance | Maria Chi |
| 3 | Anna Ming | Finance | Maria Chi |
여기서:
employee_id— 기본키야.department랑department_manager— 비키 속성이야.
처음엔 문제 없어 보이지만, 자세히 보면 department_manager는 employee_id가 아니라 department에 의존하고 있어. 그래서 트랜지티브 의존성이 생기는 거지: employee_id → department → department_manager.
생길 수 있는 문제들
만약 부서장의 이름(예: "Finance" 부서장)이 바뀌면, 그 부서가 들어간 모든 행을 다 업데이트해야 해. 만약 한 줄이라도 빼먹으면 데이터가 불일치하게 돼. 이거 진짜 골치 아픈데, 피할 수 있어.
테이블을 3NF로 바꾸기
트랜지티브 의존성을 없애려면, 테이블을 두 개로 나누면 돼. 하나는 직원 정보, 다른 하나는 부서 정보를 저장하는 거지.
employees 테이블
| employee_id | name | department |
|---|---|---|
| 1 | Otto Lin | 마케팅 |
| 2 | Alex Song | 재무 |
| 3 | Anna Ming | 재무 |
departments 테이블
| department | department_manager |
|---|---|
| 마케팅 | Leo Zhang |
| 재무 | Maria Chi |
이제 구조가 깔끔해졌고, 각 테이블이 자기 역할만 해:
employees테이블은 직원 정보를 저장해.departments테이블은 부서와 그 매니저 정보를 저장해.
만약 부서장이 바뀌면, departments 테이블의 한 줄만 업데이트하면 돼. 직원 테이블의 모든 행을 바꿀 필요 없어.
테이블이 3NF를 위반하는지 어떻게 알 수 있을까?
테이블이 3NF를 위반하는지 확인하려면:
- 트랜지티브 의존성이 있는지 봐. 예를 들어, 속성 A가 속성 B에 의존하고, B가 속성 C에 의존하는 경우.
- 모든 비키 속성이 기본키에 직접적으로 의존하는지 확인해. 만약 어떤 게 다른 비키 속성에 의존하면, 그 테이블은 3NF가 아니야.
실전 예시: 상점
sales 테이블을 보자. 이 테이블은 판매 정보를 담고 있어:
| sale_id | product_name | product_price | customer_name |
|---|---|---|---|
| 1 | 휴대폰 | 20 000 | Otto Lin |
| 2 | 노트북 | 50 000 | Alex Song |
| 3 | 휴대폰 | 20 000 | Anna Ming |
여기선 상품 가격 정보가 판매마다 반복되고 있어. 만약 가격이 바뀌면, 데이터가 바로 불일치하게 돼.
3NF 위반을 없애려면, 테이블을 두 개로 나누자:
sales테이블은 판매 정보를 저장해.products테이블은 상품과 가격 정보를 저장해.
sales 테이블
| sale_id | product_id | customer_name |
|---|---|---|
| 1 | 1 | Otto Lin |
| 2 | 2 | Alex Song |
| 3 | 1 | Anna Ming |
products 테이블
| product_id | product_name | product_price |
|---|---|---|
| 1 | 휴대폰 | 20 000 |
| 2 | 노트북 | 50 000 |
이제 상품 가격이 바뀌면, products 테이블의 한 줄만 업데이트하면 되고, 데이터 일관성도 유지돼.
실습 과제
여기 문제 하나! students_courses 테이블이 이렇게 있어:
| student_id | student_name | course_name | teacher_name |
|---|---|---|---|
| 1 | Otto Lin | 수학 | Maria Chi |
| 2 | Alex Song | 프로그래밍 | Leo Zhang |
| 1 | Otto Lin | 프로그래밍 | Leo Zhang |
이 테이블을 3NF에 맞게 나눠봐. 힌트: students, courses, teachers 이렇게 세 개의 테이블을 만들고, 서로 잘 연결해야 해.
왜 3NF를 지켜야 할까?
왜 굳이 세 번째 정규형(3NF)까지 신경 써야 할까? 진짜로 삶이 편해지거든. 테이블이 3NF로 정리되면, 데이터가 깔끔해져 — 쓸데없는 중복이 없으니까 실수로 뭔가 망가뜨릴 확률도 줄어들어. 업데이트도 훨씬 쉽고 빠르지. 왜냐면 한 군데만 바꾸면 되니까, 모든 행을 복붙할 필요가 없어.
그리고 데이터베이스 구조도 더 유연해져. 새 필드를 추가하거나 기존 걸 바꿀 때, 전체 시스템을 뜯어고칠 필요가 없어.
근데, 항상 그렇듯이 너무 정규화에 집착하면 테이블이 너무 잘게 쪼개지고, JOIN이 많은 복잡한 쿼리가 생길 수 있어. 이러면 오히려 느려질 수도 있지. 그러니까 적당히 하는 게 중요해. 꼭 필요한 곳만 정규화하고, 약간의 중복이 더 편하면 그냥 둬도 돼.
이제 더 깊이 들어가 보자! 테이블 간 관계를 제대로 설계하고, 진짜 편하고 믿을 만한 데이터베이스 만드는 법을 배울 거야. 자, 멋진 데이터베이스 설계를 향해 고고!
GO TO FULL VERSION