정규화 (Normalization)
한눈에 보기
정규화는 함수 종속을 기준으로 테이블을 분리해 중복과 이상 현상을 막는 설계 과정이다. 제1정규형부터 BCNF까지 각 단계가 제거하는 종속 관계와 예시, 반정규화와의 균형을 다룬다.
최종 업데이트 2026.09.17
정규화(Normalization)는 관계형 데이터베이스에서 데이터 중복을 줄이고 이상 현상(Anomaly)을 막기 위해, 함수 종속 관계를 기준으로 테이블을 여러 개의 작은 테이블로 나누는 설계 과정이다. 제1정규형부터 BCNF까지 단계적으로 진행되며, 각 단계는 특정한 종류의 잘못된 종속 관계를 제거한다.
정규화가 필요한 이유
하나의 테이블에 여러 주제의 정보를 함께 저장하면 같은 값이 여러 행에 중복되고, 그 결과 삽입 이상, 갱신 이상, 삭제 이상이 발생한다. 예를 들어 주문 테이블에 고객의 주소까지 저장하면 고객이 이사할 때 그 고객의 모든 주문 행을 수정해야 하고 하나라도 놓치면 데이터가 어긋난다. 정규화는 "하나의 사실은 한 곳에만 저장한다"는 원칙을 구조적으로 강제해서 이런 문제를 원천 차단한다.
정규화의 판단 기준은 함수 종속(Functional Dependency)이다. 속성 X의 값이 정해지면 속성 Y의 값이 하나로 정해질 때 Y는 X에 함수적으로 종속되었다고 하며, X를 결정자(Determinant)라고 부른다.
정규화 단계
제1정규형(1NF)
모든 속성이 원자값(Atomic Value)을 가져야 한다. 하나의 칸에 "010-1111-2222, 010-3333-4444"처럼 여러 값을 콤마로 이어 넣거나, 전화번호1, 전화번호2 같은 반복 그룹을 두는 구조를 없앤다. 여러 값이 필요하면 별도의 행이나 별도의 테이블로 분리한다.
제2정규형(2NF)
제1정규형을 만족하면서, 키가 아닌 모든 속성이 기본키 전체에 완전 함수 종속이어야 한다. 기본키가 (학번, 과목코드)인 테이블에서 학생 이름은 학번만으로 결정되므로 부분 함수 종속이다. 이런 속성을 학번을 키로 하는 별도 테이블로 분리한다. 기본키가 단일 속성이면 부분 종속이 생길 수 없으므로 자동으로 만족한다.
제3정규형(3NF)
제2정규형을 만족하면서, 키가 아닌 속성이 다른 키가 아닌 속성에 종속되는 이행적 종속(Transitive Dependency)이 없어야 한다. 학번이 학과를 결정하고 학과가 학과 사무실 위치를 결정한다면, 사무실 위치는 학번에 이행적으로 종속된 것이다. 학과 정보를 별도 테이블로 분리해서 해결한다.
BCNF(Boyce-Codd Normal Form)
모든 함수 종속에서 결정자가 후보키여야 한다. 제3정규형을 만족하더라도 후보키가 아닌 속성이 결정자 역할을 하는 경우가 남을 수 있는데, 예를 들어 한 교수가 한 과목만 가르친다는 규칙이 있으면 교수가 과목의 결정자가 되지만 교수는 후보키가 아니다. 이런 종속을 분리하는 것이 BCNF이며, 강한 제3정규형이라고도 부른다. 이후 다치 종속을 다루는 제4정규형, 조인 종속을 다루는 제5정규형이 있지만 실무 설계는 대체로 제3정규형이나 BCNF 수준에서 마무리한다.
단계별 요약 비교
| 단계 | 제거 대상 | 핵심 조건 |
|---|---|---|
| 1NF | 반복 그룹, 다중 값 | 모든 속성이 원자값을 가진다 |
| 2NF | 부분 함수 종속 | 비키 속성이 기본키 전체에 종속된다 |
| 3NF | 이행적 종속 | 비키 속성이 비키 속성에 종속되지 않는다 |
| BCNF | 후보키가 아닌 결정자 | 모든 결정자가 후보키다 |
정규화 예시
주문 정보를 한 테이블에 담은 구조를 3NF까지 분리하면 다음과 같은 형태가 된다.
-- 정규화 이전: 고객과 상품 정보가 주문마다 중복 저장된다
-- orders(order_id, customer_name, customer_addr, product_name, price, qty)
-- 정규화 이후
CREATE TABLE customer (
customer_id BIGINT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
address VARCHAR(200)
);
CREATE TABLE product (
product_id BIGINT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL
);
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY,
customer_id BIGINT NOT NULL REFERENCES customer (customer_id),
ordered_at DATETIME NOT NULL
);
CREATE TABLE order_item (
order_id BIGINT NOT NULL REFERENCES orders (order_id),
product_id BIGINT NOT NULL REFERENCES product (product_id),
qty INT NOT NULL,
PRIMARY KEY (order_id, product_id)
);
반정규화와의 균형
정규화를 높은 단계까지 적용하면 테이블 수가 늘어나고, 조회할 때마다 여러 테이블을 조인(Join)해야 하므로 읽기 성능이 떨어질 수 있다. 그래서 조회가 압도적으로 많은 서비스에서는 의도적으로 중복을 허용하는 반정규화(Denormalization)를 병행한다. 자주 조인되는 컬럼을 복사해 두거나, 집계 결과를 미리 계산해 저장하는 방식이 대표적이다.
반정규화는 이상 현상의 위험을 다시 불러오므로, 중복 데이터를 동기화하는 책임을 애플리케이션이나 배치 작업이 져야 한다. 일반적인 접근은 먼저 3NF 수준으로 정규화한 뒤, 실제 성능 측정 결과를 근거로 필요한 부분만 선별적으로 반정규화하는 것이다.
면접에서 이렇게 물어본다
- 제1정규형부터 제3정규형까지 각 단계에서 무엇을 제거하는지 예시와 함께 설명해 보라.
- 제3정규형과 BCNF의 차이는 무엇인가.
- 부분 함수 종속과 이행적 종속을 구분해서 설명할 수 있는가.
- 정규화의 장점과 단점은 무엇이고, 반정규화는 언제 고려하는가.
- 정규화가 이상 현상을 어떻게 예방하는지 설명해 보라.
데이터베이스에서 같이 읽기
- 이상 현상 (Anomaly)이상 현상은 테이블 설계가 잘못되어 삽입, 갱신, 삭제 과정에서 데이터 불일치나 손실이 생기는 현상이다. 삽입, 갱신, 삭제 이상의 세 종류와 원인인 함수 종속, 해결책인 정규화까지 예시와 함께 정리한다.
- 데이터베이스 커넥션 풀 (Database Connection Pool)데이터베이스 연결을 미리 만들어 재사용하는 커넥션 풀의 동작 원리와 필요성을 다룬다. HikariCP 설정, 풀 크기 계산, 타임아웃과 고갈 문제를 실무 관점에서 정리했다.
- 인덱스 (Index)인덱스는 컬럼 값과 저장 위치를 별도 자료구조로 정리해 검색 속도를 높이는 장치다. B+Tree 동작 원리, 클러스터드와 논클러스터드 비교, 복합 인덱스와 커버링 인덱스, 설계 시 주의점을 다룬다.
- 데이터베이스 레플리케이션 (Database Replication)원본 데이터베이스의 변경을 레플리카에 복제해 읽기 부하와 장애를 분산하는 구조를 다룬다. 동기와 비동기 복제, 복제 지연, 읽기 일관성과 장애 전환을 정리했다.
이 개념, 내 코드에서는 어떻게 물어볼까요
데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.
공고 넣고 시작하기