중복을 없애 갱신 이상을 막는 작업이고, 기준은 함수 종속입니다. 어떤 컬럼이 어떤 컬럼을 결정하는지를 보고 테이블을 나눕니다.
정규화 (Normalization)
목적
데이터 중복 최소화 + 이상 현상(Anomaly) 방지
정규화 단계
| 단계 | 규칙 | 핵심 |
|---|
| 1NF | 원자값만 | 하나의 셀에 하나의 값 |
| 2NF | 부분 종속 제거 | 복합키의 일부에만 종속 X |
| 3NF | 이행 종속 제거 | A→B→C면 A→C 분리 |
예시: 1NF 위반 → 정규화
1NF 위반. 한 칸에 값이 여럿이다
1NF 적용. 한 칸에 값 하나씩
왜 나누면 이상이 사라지나
정규화는 규칙 암기가 아니라 한 사실을 한 곳에만 두기입니다. 두 곳에 있으면 세 가지가
생깁니다.
| 이상 | 어떻게 나타나나 |
|---|
| 갱신 | 한 곳만 고쳐서 두 값이 달라진다 |
| 삽입 | 아직 모르는 값 때문에 행을 못 넣는다 |
| 삭제 | 행을 지우니 관계 없는 사실까지 사라진다 |
셋째가 가장 늦게 발견됩니다. 주문을 지웠는데 그 상품의 분류 정보가 함께 사라지는 식입니다.
한 곳에만 두면 셋 다 구조적으로 생길 수 없습니다.
나눈 대가
나누면 읽을 때 붙여야 합니다. 그것이 비용입니다.
목록 화면 하나에 표 다섯 개를 붙이면 느려진다
붙이는 개수가 늘면 계획이 나빠질 확률도 오른다
그래서 읽기가 압도적으로 많고 그 값이 거의 안 바뀌면 일부를 다시 합칩니다. 다만 합치는
순간 위의 세 이상이 돌아오므로, 무엇으로 맞출지를 함께 정해야 합니다.
반정규화 (Denormalization)
조회 성능을 위해 의도적으로 중복 허용
| 상황 | 선택 |
|---|
| 조인이 너무 많아 느림 | 반정규화 고려 |
| 데이터 정합성 중요 | 정규화 유지 |
| 읽기 > 쓰기 | 반정규화 유리 |
| 쓰기 > 읽기 | 정규화 유지 |
실무 포인트
- 보통 3NF까지가 실무 표준
- OLTP(트랜잭션): 정규화 중심
- OLAP(분석): 반정규화 (스타 스키마)
Q.정규화를 왜 하나요? 장단점을 설명해주세요
같은 사실을 여러 곳에 두지 않아 갱신 이상을 막기 위해서입니다.
| 이상 | 예 |
|---|
| 갱신 이상 | 사용자 이메일을 바꿨는데 주문 테이블의 사본이 그대로다 |
| 삽입 이상 | 아직 주문이 없는 상품을 등록할 자리가 없다 |
| 삭제 이상 | 마지막 주문을 지웠더니 상품 정보까지 사라진다 |
| 장점 | 단점 |
|---|
| 중복이 줄어 저장 공간이 준다 | 조인이 늘어난다 |
| 갱신이 한 곳에서 끝난다 | 조회 쿼리가 복잡해진다 |
| 무결성을 제약으로 지킬 수 있다 | 조회 성능이 떨어질 수 있다 |
흔한 실수: 정규화의 목적을 "저장 공간 절약"으로 답하는 것. 디스크가 싸진 지금 그것은 부차적이고, 한 사실을 한 곳에만 두어 갱신 이상을 없애는 것이 본질입니다.
Q.1NF, 2NF, 3NF 차이를 예시로 설명해주세요
| 단계 | 조건 | 위반 예 |
|---|
| 1NF | 한 칸에 값이 하나 | 수강과목 칸에 "수학, 영어" |
| 2NF | 1NF 이면서 기본키 전체에 종속 | 키가 (학번, 과목)인데 학생이름이 학번에만 종속 |
| 3NF | 2NF 이면서 키가 아닌 컬럼끼리 종속 없음 | 학번이 학과를 정하고 학과가 학과장을 정한다 |
2NF 는 복합 키일 때만 문제가 됩니다. 키가 하나면 부분 종속이 있을 수 없어 자동으로 만족합니다.
3NF 위반은 이행 종속이라고 부릅니다. 학과장을 바꾸려면 그 학과 학생 행을 모두 고쳐야 하는데, 학과 테이블을 분리하면 한 곳만 고치면 됩니다.
흔한 실수: 정의만 외워 답하는 것. 각 단계가 어떤 갱신 이상을 없애는지를 함께 말하는 것이 좋습니다. 실무에서는 3NF 까지 맞추고 필요한 곳만 반정규화하는 것이 일반적입니다.
Q.실무에서 정규화를 안 하는 경우가 있나요?
| 상황 | 이유 |
|---|
| 시점의 사실을 남겨야 할 때 | 주문 당시 가격과 주소는 원본이 바뀌어도 그대로여야 한다 |
| 조회 성능이 병목일 때 | 조인 대신 미리 계산한 값을 둔다 |
| 집계 값 | 게시글의 댓글 수를 매번 세지 않고 컬럼으로 둔다 |
| 분석용 저장소 | 조회 전용이라 중복을 감수하고 조인을 없앤다 |
| 로그와 이벤트 | 그 시점의 상태를 통째로 남긴다 |
첫 번째는 반정규화가 아니라 다른 사실을 저장하는 것입니다. 주문 시점의 가격은 상품의 현재 가격과 다른 데이터이므로 중복이 아닙니다. 이름을 ordered_price 처럼 지어 의도를 드러내면 혼동이 줄어듭니다.
흔한 실수: 시점 스냅샷을 반정규화로 설명하는 것. 갱신이 필요 없는 값이므로 정합성 문제가 애초에 없습니다. 진짜 반정규화는 원본과 사본이 함께 바뀌어야 하는 경우입니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.