ERD 정규화 및 반정규화 전략
- 데이터베이스 설계에서의 정규화 (Normalization)와 반정규화(De-normalization, 역정규화)는 데이터의 무결성과 시스템의 성능 사이에서 균형을 잡는 가장 핵심적인 두 축임
- 두 개념은 대립하는 것이 아니라 점진적 모델링 과정에서 상호보완적으로 적용되는 전략
- “정규화를 통해 데이터 구조를 벼리고, 반정규화를 통해 성능을 타협한다”
1. ERD 정규화 전략
- ERD 정규화 (Normalization)
- 데이터의 중복을 최소화하고, 무결성(Integrity)을 확보하여
- 삽입·수정·삭제 시 발생하는 이상 현상(Anomaly)을 제거하기 위해
- 테이블을 구조적으로 쪼개어 나가는 과정
- 제1정규화 (1NF: 원자값 확보)
- 개념:
- 테이블의 모든 속성값은 더 이상 쪼개질 수 없는 원자값(Atomic Value)이어야 함
- 현상:
- 하나의 칸에 여러 개의 데이터가 쉼표(
,) 등으로 나열되어 있으면 안됨
- 하나의 칸에 여러 개의 데이터가 쉼표(
- 해소 전략:
- 중복된 그룹을 분리하여 새로운 행(Row)이나 별도의 테이블로 독립시킴
- 예시:
학생테이블의취미컬럼에 ‘독서, 축구’가 동시에 들어가 있다면,- 이를 분리하여 다중 행으로 만들거나
학생취미테이블을 신설할 것
- 개념:
- 제2정규화 (2NF: 부분 함수 종속성 제거)
- 개념:
- 주식별자가 2개 이상으로 구성된 복합키(Composite Key)일 때,
- 복합키의 일부분에만 종속되는 일반 속성이 없어야 함 (완전 함수 종속 만족)
- 현상:
- 복합키 중 하나에만 종속되는 속성이 있으면
- 해당 키의 데이터가 바뀔 때 불필요한 데이터 중복과 이상 현상이 발생함
- 해소 전략:
- 부분 종속되는 속성과 해당 주식별자 조각을 떼어내어 별도의 테이블로 분리
- 예시:
수강신청테이블(주식별자:학번+과목코드)에강의실명이 있다면,강의실명은과목코드에만 종속되므로과목테이블로 뜯어내야 함
- 개념:
- 제3정규화 (3NF: 이행적 함수 종속성 제거)
- 개념:
- 주식별자가 아닌 일반 속성들끼리 서로 종속 관계를 가지면 안됨
- \(A \rightarrow B\) 이고 \(B \rightarrow C\) 이면 \(A \rightarrow C\) 가 성립하는 관계 제거
- 주식별자가 아닌 일반 속성들끼리 서로 종속 관계를 가지면 안됨
- 현상:
- 일반 속성이 다른 일반 속성을 결정하게 되면 데이터의 일관성이 깨지기 쉬움
- 해소 전략:
- 이행적 종속을 유발하는 일반 속성들을 모아 새로운 부모 테이블을 개설
- 예시:
사원테이블(주식별자:사원번호)에부서코드와부서명이 함께 있다면,사원번호가부서코드를 결정하고,부서코드가부서명을 결정하는 이행적 종속이 발생함- 따라서
부서명은부서코드와 함께부서테이블로 분리해야 함
- 개념:
2. ERD 반정규화 전략
- ERD 반정규화 (De-normalization)
- 정규화된 데이터 모델이 시스템의 조회(Select) 성능을 극대화하기 위해
- 의도적으로 중복, 통합, 분리를 수행하는 엔지니어링 기법
- 반정규화가 필요한 이유 (Triggers)
- 정규화를 엄격하게 거치면 테이블이 수십, 수백 개로 잘게 쪼개짐
- 이 상태에서 화면 하나에 데이터를 보여주려면 수많은 테이블을
JOIN해야 함 - 대용량 데이터 환경이나 고속 로그 처리가 필요한 스마트팩토리 IoT 시스템, 금융 거래 시스템 등에서는 과도한 Join 비용이 시스템 마비를 초래하므로 반정규화 전략이 필수적
대표적인 3대 반정규화 기법
- 테이블 통합 및 분할 (Table Merge & Split)
- 두 테이블 통합:
- \(1:1\) 관계나 \(1:N\) 관계에서 Join이 너무 자주 발생해 성능이 떨어질 때,
- 두 테이블을 하나로 합쳐 Join을 원천 차단
- 수평 분할 (Partitioning):
- 하나의 테이블에 대용량 데이터(예: 수억 건의 로그)가 쌓일 때,
- 기간별(월별, 년별) 또는 지역별로 테이블을 쪼개어 검색 범위를 줄임
- 수직 분할 (Column Split):
- 테이블의 컬럼 중 용량이 매우 큰 텍스트(BLOB/TEXT)나 거의 조회되지 않는 보안 속성들을
- 별도 테이블로 분리하여 디스크 I/O 효율을 높임
- 두 테이블 통합:
- 컬럼 중복 (Column Redundancy)
- 계산된 컬럼 추가:
- 조회가 일어날 때마다
SUM(),AVG()같은 집계 함수를 실시간으로 계산하면 과부하가 걸림 - 연산 결과를 담아둘
총주문금액,평균점수같은 컬럼을 미리 테이블에 준비해두고 업데이트하는 방식
- 조회가 일어날 때마다
- 이력 테이블 최신값 중복:
- 수많은 변경 이력 데이터 중 ‘현재 상태’나 ‘최신 단가’를 조회하기 위해 매번 이력 테이블을 서브쿼리로 뒤지는 비용을 아끼기 위해,
- 메인 테이블에
최신상태값컬럼을 중복하여 보관
- 계산된 컬럼 추가:
- 관계 중복 (Relationship Redundancy)
- 부모 테이블을 거쳐 조부모 테이블의 데이터를 조회하는 구조(\(A \rightarrow B \rightarrow C\))에서,
- 중간 단계를 건너뛰고 \(A\)에서 \(C\)로 직접 갈 수 있는 외래키(FK) 선을 하나 더 연결하는 기법
- 테이블 통합 및 분할 (Table Merge & Split)
- 정규화와 반정규화의 조화 전략
- 많은 초급 개발자들이 하는 실수
- “처음부터 성능이 걱정되니 대충 뭉뚱그려서 테이블을 하나로 짜자”는 식의 설계를 하는 것
- 이 경우 무결성이 깨져 데이터가 오염되는 재앙을 맞이하기 쉬움
- 정석적인 아키텍처 가이드라인
- “선(先) 정규화, 후(後) 반정규화” 원칙을 고수할 것
- 먼저 3정규화 단계까지 완벽하게 정제된 논리 ERD를 완성해야
- 데이터의 본질적 구조와 비즈니스 규칙이 명확히 보이게 됨
- 반정규화는 철저히 ‘데이터 증적(로그/성능 측정 결과)’에 기반해야 함
- 시스템 개발 단계나 실제 운영 단계에서 쿼리 성능 테스트(Explain, 응답 속도 체크)를 진행하고,
- 성능 저하의 주범이 과도한 Join으로 밝혀졌을 때에만
- 타겟 테이블을 지정하여 제한적으로 반정규화를 적용해야
- 안정적인 데이터베이스를 완성할 수 있음