데이터모델링 - 정규화/반정규화
🎯데이터모델링 - 정규화/반정규화
데이터베이스 설계에서 중요한 개념 중 하나가 바로 정규화(Normalization) 와 반정규화(Denormalization) 이다.
정규화는 데이터 중복과 이상현상(Anomaly)을 제거하기 위한 기법이고, 반정규화는 성능 향상이나 운영 효율성을 위해 정규화를 의도적으로 완화하는 과정이다.
—
1. 정규화 (Normalization)
정의
관계형 데이터베이스에서 데이터의 중복을 최소화하고 무결성을 보장하기 위해 테이블을 분해하는 과정이다.
정규화 단계
| 단계 | 설명 | 특징 |
|---|---|---|
| 1NF (제1정규형) | 원자값으로 분해 | 반복 속성 제거 |
| 2NF (제2정규형) | 부분 종속 제거 | 복합키 → 부분 종속 제거 |
| 3NF (제3정규형) | 이행 종속 제거 | 기본키가 아닌 속성 간 종속 제거 |
| BCNF | 모든 결정자가 후보키 | 더 엄격한 제약 |
예시
0단계 (비정규화된 상태)
주문(주문ID, 고객ID, 고객명, 주소, 주문일자, 상품ID, 상품명, 단가, 수량)
한 테이블 안에 고객 + 주문 + 상품 정보가 모두 들어 있음
- 문제점
- 고객 주소 변경 시, 해당 고객이 주문한 모든 행을 수정해야 함 (갱신 이상)
- 상품명이 바뀌면 역시 모든 주문 레코드를 수정해야 함 (갱신 이상)
- 신규 고객을 추가하려면 주문ID도 필요해 추가 불가 (삽입 이상)
- 주문 삭제 시 고객 정보까지 함께 사라짐 (삭제 이상)
1NF (제1정규형) – 원자값 보장
- 주소를 “시/도 + 구 + 도로명” 으로 나눔 → 원자값 보장
변경 후 테이블
주문(주문ID, 고객ID, 고객명, 시도, 구, 도로명, 주문일자, 상품ID, 상품명, 단가, 수량)
→ 이제 주소 컬럼이 더 이상 복합값을 갖지 않음.
2NF (제2정규형) - 부분 종속 제거
- 현재 기본키 후보 : (주문ID, 상품ID) → 주문 1건에 여러 상품이 들어올 수 있기 떄문에.
- 문제 : 상품명, 단가는 상품ID에만 종속됨 → 부분 종속 발생
- 해결 : 상품 테이블 분리
변경 후 테이블
주문(주문ID, 고객ID, 주문일자)
주문상세(주문ID, 상품ID, 수량)
상품(상품ID, 상품명, 단가)
→ 상품명, 단가는 상품ID 기준으로만 관리 → 데이터 중복 제거
3NF (제3정규형) – 이행 종속 제거
- 문제: 고객명, 시도, 구, 도로명은 고객ID에 종속 → 주문 테이블에 두면 이행 종속 발생
- 해결: 고객 테이블 분리
최종 구조
고객(고객ID, 고객명, 시도, 구, 도로명)
주문(주문ID, 고객ID, 주문일자)
주문상세(주문ID, 상품ID, 수량)
상품(상품ID, 상품명, 단가)
→ 이제 모든 속성은 기본키에만 직접 종속 → 이상현상 제거 + 무결성 보장
결과
- 1NF : 주소를 세부 컬럼으로 분리 → 원자값 보장
- 2NF : 상품 정보를 별도 테이블로 분리 → 부분 종속 제거
- 3NF : 고객 정보를 별도 테이블로 분리 → 이행 종속 제거
장단점 요약
- 장점:
- 데이터 중복 최소화
- 삽입/삭제/갱신 이상현상 제거
- 무결성 보장
- 단점:
- 테이블 수 증가 → Join 연산 과다
- 조회 성능 저하 가능
2. 반정규화 (Denormalization)
정의
조회 성능을 높이고, 개발 편의성을 확보하기 위해 정규화를 일부 해제하는 과정이다.
주요 기법
| 기법 | 설명 | 예시 |
|---|---|---|
| 테이블 병합 | 자주 Join하는 마스터/상세 테이블 통합 | 주문 + 주문상세 통합 |
| 테이블 분할 | 수평/수직 분할로 성능 향상 | 대량 데이터 → 기간별 테이블 분할 |
| 중복 컬럼 추가 | 합계, 카운트 값 저장 | 주문건수, 재고수량 컬럼 |
| 파생 데이터 저장 | 계산식 결과 미리 저장 | 총금액 = 단가 * 수량 |
예시
정규화가 끝난 상태의 테이블
고객(고객ID, 고객명, 시도, 구, 도로명)
주문(주문ID, 고객ID, 주문일자)
주문상세(주문ID, 상품ID, 수량)
상품(상품ID, 상품명, 단가)
→ 이 구조는 무결성 보장에는 좋지만, 주문 조회 시에는 항상 다중 조인이 필요하다.
예시
1
2
3
4
5
6
SELECT C.고객명, O.주문일자, SUM(P.단가 * OD.수량) AS 총금액
FROM 주문 O
JOIN 고객 C ON O.고객ID = C.고객ID
JOIN 주문상세 OD ON O.주문ID = OD.주문ID
JOIN 상품 P ON OD.상품ID = P.상품ID
GROUP BY C.고객명, O.주문일자;
고객명 중복 저장
- 주문 테이블에 고객명을 추가 저장
- 고객 정보를 위해 JOIN 고객을 하지 않아도 됨
주문(주문ID, 고객ID, 고객명, 주문일자)
장점
- 조회 속도 향상
단점
- 고객명이 변경되면 주문 테이블 전체를 수정해야 함 → 갱신 이상
총금액 파생 컬럼 추가
- 주문 테이블에 총금액 컬럼을 별도로 추가
주문(주문ID, 고객ID, 주문일자, 총금액)
장점
- 매번 SUM(단가 * 수량) 계산할 필요 없음
- 보고서 조회, 통계 처리 시 빠름
단점
- 주문상세 변경 시 총금액을 반드시 동기화해야 함 → 무결성 관리 부담
주문 + 주문상세 테이블 병합
- 주문과 주문상세를 합쳐 하나의 테이블로 구성
주문내역(주문ID, 고객ID, 고객명, 주문일자, 상품ID, 상품명, 단가, 수량, 총금액)
장점
- 하나의 테이블에서 모든 주문 데이터 조회 가능
- 보고서, 통계, 대량 조회 시 유리
단점
- 데이터 중복 증가
- 고객명, 상품명 변경 시 대량 Update 필요
결과
- 정규화 : 중복 최소화, 무결성 ↑, 성능 ↓
- 반정규화 : 성능 ↑, 관리 편의성 ↑, 무결성 ↓
결국, 반정규화는 성능과 편의성을 위해 무결성을 일부 희생 하는 것이라고 생각한다.
장단점 요약
- 장점:
- 조회 성능 개선
- SQL 단순화
- 응답 속도 향상
- 단점:
- 데이터 중복 발생
- 무결성 관리 비용 증가
- 갱신 부하
3. 정규화 vs 반정규화 비교
| 구분 | 정규화 | 반정규화 |
|---|---|---|
| 목적 | 무결성 보장, 이상현상 제거 | 성능 향상, 단순화 |
| 데이터 중복 | 최소화 | 의도적 허용 |
| 무결성 | 높음 | 낮음 |
| 성능 | 조회 성능 저하 가능 | 조회 성능 향상 |
| 적용 시점 | 설계/분석 단계 | 구현/튜닝 단계 |
4. 결론
- 정규화는 데이터 품질과 무결성을 위한 필수 과정
- 반정규화는 성능 최적화를 위한 선택적 과정
- 즉, 정규화 → 기본 원칙, 반정규화 → 상황에 따른 예외적 적용
데이터모델링은 이 두 가지를 적절히 조화시키는 것이 중요하다.
분석 단계에서는 철저히 정규화하여 논리적 모델을 만들고, 실제 운영 단계에서는 > 성능 이슈에 맞추어 필요한 부분만 반정규화를 적용해야 한다.
조회 성능이 중요한 BI, 리포트, 트랜잭션 처리 시스템에서는 반정규화 적극 활용데이터 무결성이 더 중요한 금융/안전/공공 시스템에서는 정규화 유지 —
📚 참고자료
- C.J. Date, Database System Concepts
- 한국데이터산업진흥원, 데이터모델링 표준 가이드라인