
데이터베이스 설계의 핵심은 정규화(Normalization)와 비정규화(Denormalization) 사이의 줄다리기에 있음.
정규화는 데이터의 중복을 제거하여 데이터 무결성과 유연성을 확보하는 과정임. 반면 비정규화는 읽기 성능을 극대화하기 위해 의도적으로 중복을 허용하는 성능 최적화 전략임.
정규화는 데이터 변경(CUD) 비용을 줄이고 일관성을 지키는 데 유리하지만, 복잡한 조회(Read) 시 JOIN으로 인한 성능 저하를 감수해야 함. 비정규화는 JOIN을 최소화해 조회 성능을 끌어올리지만, 데이터 중복으로 인한 수정 비용 증가와 잠재적 불일치라는 대가를 치름. 따라서 성공적인 데이터 모델링은 시스템의 읽기/쓰기 패턴과 데이터 정합성 요구 수준을 정확히 분석하여 두 전략의 균형점을 찾는 것.
데이터의 중복을 제거하며 테이블을 논리적으로 분해하는 과정. 데이터 구조를 명확히 하고, 데이터 삽입/수정/삭제 시 발생할 수 있는 이상 현상(Anomaly)을 방지하는 것이 주 목적임.
주요 정규형
장점
단점
조회 성능이 매우 중요한 경우, 정규화된 모델에 의도적으로 중복을 허용하거나 테이블을 병합하여 JOIN의 비용을 줄이는 과정임. 정규화의 원칙을 위배하여 성능을 얻는 트레이드오프 전략임.
주요 기법
posts 테이블에 author_username 추가)comment_count 컬럼 추가)장점
단점
INSERT, UPDATE 비용이 커짐.일단 정규화하고, 성능 병목 지점에서 비정규화 검토
정규화를 우선하는 경우 (Write-heavy, OLTP 시스템)
비정규화를 고려하는 경우 (Read-heavy, OLAP 시스템)
사용자(users)의 등급(level) 정보가 있고, 사용자가 작성한 게시물(posts)을 조회하는 시나리오.
-- 1. 정규화된 테이블 설계 (Normalized)
-- 사용자 정보와 게시물 정보를 완벽히 분리. 사용자 등급 변경 시 users 테이블만 수정하면 됨.
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
user_level VARCHAR(20) DEFAULT 'BRONZE'
);
CREATE TABLE posts (
post_id INT PRIMARY KEY,
author_id INT, -- Foreign Key
title VARCHAR(255) NOT NULL,
FOREIGN KEY (author_id) REFERENCES users(user_id)
);
-- 게시물 조회 시, 작성자 이름과 등급을 알려면 반드시 JOIN이 필요.
SELECT p.title, u.username, u.user_level
FROM posts p
JOIN users u ON p.author_id = u.user_id
WHERE p.post_id = 101;
-- 2. 비정규화된 테이블 설계 (Denormalized)
-- 게시물 테이블에 작성자 이름과 등급을 중복 저장하여 JOIN을 제거.
CREATE TABLE posts_denormalized (
post_id INT PRIMARY KEY,
author_id INT,
author_username VARCHAR(50), -- 사용자 이름 중복 저장
author_level VARCHAR(20), -- 사용자 등급 중복 저장
title VARCHAR(255) NOT NULL
);
-- JOIN 없이 단일 테이블 조회만으로 모든 정보를 가져와 성능상 유리.
SELECT title, author_username, author_level
FROM posts_denormalized
WHERE post_id = 101;
-- 3. 치명적인 트레이드오프: 데이터 수정 시 비용 비교
-- 사용자 ID 1번 유저의 등급이 'BRONZE'에서 'GOLD'로 변경되는 상황
-- [정규화 모델] 단 1개의 레코드만 수정하면 끝. 데이터 정합성 완벽 보장.
UPDATE users SET user_level = 'GOLD' WHERE user_id = 1;
-- [비정규화 모델] 해당 유저가 작성한 모든 게시물의 author_level을 일일이 찾아 수정해야 함.
-- 만약 이 과정에서 일부 레코드가 누락되면 데이터 불일치(Inconsistency) 발생.
UPDATE posts_denormalized SET author_level = 'GOLD' WHERE author_id = 1;
JOIN이나 WHERE 절에 사용되는 컬럼에 인덱스를 생성하면 정규화된 상태에서도 드라마틱한 성능 향상을 기대할 수 있음.JOIN이나 집계 쿼리의 결과를 물리적인 테이블로 미리 저장해두고, 원본 데이터가 변경될 때마다 DBMS가 주기적으로 결과를 갱신해줌. 성능과 정합성 사이의 균형을 맞추는 강력한 도구.