Contents
see List작성일 2025. 11. 30.
데이터베이스 정규화와 반정규화 전략
정규화는 데이터 중복을 제거하고 무결성을 보장하는 설계 기법이고, 반정규화는 성능을 위해 의도적으로 중복을 허용하는 기법입니다. 상황에 맞는 적절한 균형이 중요합니다.
언제 사용하나요?
- 정규화: OLTP 시스템, 데이터 무결성 중요, 쓰기 빈번
- 반정규화: OLAP/분석, 읽기 성능 중요, 복잡한 조인 제거
정규화 단계
제1정규형 (1NF): 원자값만 저장
- 하나의 컬럼에 여러 값 금지
- 반복 그룹 제거
-- 위반 (전화번호가 여러 개)
| 이름 | 전화번호 |
| 홍길동 | 010-1234, 010-5678 |
-- 1NF 적용
| 이름 | 전화번호 |
| 홍길동 | 010-1234 |
| 홍길동 | 010-5678 |
제2정규형 (2NF): 부분 함수 종속 제거
- 기본키 전체에 종속되어야 함
-- 위반 (수강 테이블, 교수명은 과목에만 종속)
| 학번 | 과목코드 | 교수명 | 성적 |
| 001 | CS101 | 김교수 | A |
-- 2NF 적용 (테이블 분리)
[수강] 학번, 과목코드, 성적
[과목] 과목코드, 교수명
제3정규형 (3NF): 이행적 함수 종속 제거
- 비키 컬럼이 다른 비키 컬럼에 종속 안됨
-- 위반 (부서명은 부서코드에 종속)
| 사원번호 | 부서코드 | 부서명 |
| E001 | D01 | 개발팀 |
-- 3NF 적용
[사원] 사원번호, 부서코드
[부서] 부서코드, 부서명
BCNF: 모든 결정자가 후보키반정규화 기법
1. 테이블 병합
-- 1:1 관계 테이블 합치기
-- 정규화: 회원, 회원상세 분리
-- 반정규화: 회원 테이블에 상세 정보 포함
2. 컬럼 중복
-- 조인 제거를 위해 다른 테이블 컬럼 복사
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
user_name VARCHAR(50), -- users.name 복사
product_id INT,
product_name VARCHAR(100), -- products.name 복사
...
);
3. 파생 컬럼 추가
-- 계산 결과 미리 저장
CREATE TABLE orders (
...
order_total DECIMAL(10,2), -- SUM(item.price * qty) 결과
item_count INT -- COUNT(*) 결과
);
4. 테이블 분할
-- 수평 분할: 행 기준 (파티셔닝)
-- 수직 분할: 컬럼 기준 (자주 쓰는 것 분리)
5. 집계 테이블
-- 통계용 요약 테이블
CREATE TABLE daily_sales_summary (
sale_date DATE PRIMARY KEY,
total_orders INT,
total_amount DECIMAL(15,2),
avg_order_value DECIMAL(10,2)
);실전 예시: 게시판
-- 정규화된 설계
CREATE TABLE posts (
post_id INT PRIMARY KEY,
user_id INT REFERENCES users(user_id),
title VARCHAR(200),
content TEXT,
created_at TIMESTAMP
);
CREATE TABLE comments (
comment_id INT PRIMARY KEY,
post_id INT REFERENCES posts(post_id),
user_id INT REFERENCES users(user_id),
content TEXT
);
-- 반정규화 적용
CREATE TABLE posts (
post_id INT PRIMARY KEY,
user_id INT,
user_name VARCHAR(50), -- 중복: 조인 제거
title VARCHAR(200),
content TEXT,
comment_count INT DEFAULT 0, -- 파생: COUNT 제거
view_count INT DEFAULT 0,
created_at TIMESTAMP
);
-- 댓글 추가 시 트리거로 comment_count 갱신
CREATE TRIGGER update_comment_count
AFTER INSERT ON comments
FOR EACH ROW
BEGIN
UPDATE posts
SET comment_count = comment_count + 1
WHERE post_id = NEW.post_id;
END;반정규화 시 고려사항
1. 데이터 동기화
-- 중복 데이터 일관성 유지 방법
-- 트리거, 배치 작업, 애플리케이션 로직
2. 저장 공간
-- 중복으로 인한 용량 증가
-- SSD 비용 vs 조인 비용 비교
3. 쓰기 성능
-- 중복 컬럼 갱신 부담
-- 읽기/쓰기 비율 고려
4. 유지보수
-- 데이터 불일치 위험
-- 문서화 필수선택 가이드
| 상황 | 권장 |
|---|---|
| OLTP (트랜잭션) | 정규화 우선 |
| OLAP (분석/리포트) | 반정규화/스타 스키마 |
| 읽기 90% 이상 | 반정규화 고려 |
| 복잡한 조인 (5개+) | 반정규화 고려 |
| 데이터 무결성 중요 | 정규화 유지 |
| 실시간 집계 | 집계 테이블 추가 |
모범 사례
- 먼저 정규화 후, 필요시 반정규화
- 반정규화 결정은 성능 테스트 기반
- 인덱스로 해결 가능한지 먼저 검토
- 캐시(Redis)로 대체 가능한지 검토
- 반정규화 시 문서화 필수