Skip to main content

11/12/2025

정규화 (Normalization)

Overview​


정규화(Normalization)는 데이터의 일관성, 최소한의 데이터 중복, 최대한의 데이터 유연성을 위해 데이터를 분해하는 과정입니다.

관계형 데이터베이스 설계에서 데이터의 중복을 최소화하고 무결성을 유지하기 위한 핵심적인 기법입니다.


목적​

1. 데이터 중복 최소화​

  • 동일한 데이터의 반복 저장 방지
  • 저장 공간 효율성 향상
  • 데이터 일관성 유지

2. 데이터 무결성 보장​

  • 삽입 이상(Insertion Anomaly) 방지
  • 갱신 이상(Update Anomaly) 방지
  • 삭제 이상(Deletion Anomaly) 방지

3. 데이터 구조의 안정성​

  • 논리적이고 직관적인 데이터 구조
  • 유지보수 용이성
  • 확장성 및 유연성 확보

정규화 단계​

정규화는 속성의 원자성 확보부터 시작하여 점진적으로 데이터 구조를 개선해 나가는 과정입니다. 개요에서 1~3+BCNF 예시 다이어그램을 그리면서 내용을 정리했습니다.

1정규화 (1NF: First Normal Form)​

정의: 기본키 설정

조건:

  • 모든 속성은 원자값(Atomic Value)을 가져야 함
  • 반복 그룹(Repeating Group) 제거
  • 각 행은 고유하게 식별 가능해야 함

적용 전 예시:

주문 테이블
-----------
주문ID | 고객명 | 상품목록
1 | 홍길동 | 사과, 바나나, 오렌지
2 | 김철수 | 우유, 빵

적용 후 예시:

주문 테이블
-----------
주문ID | 고객명 | 상품
1 | 홍길동 | 사과
1 | 홍길동 | 바나나
1 | 홍길동 | 오렌지
2 | 김철수 | 우유
2 | 김철수 | 빵

특징:

  • 다중값 속성 제거
  • 복합 속성을 단일 속성으로 분해
  • 주식별자(Primary Key) 정의 필수

2정규화 (2NF: Second Normal Form)​

정의: 기본키가 2개 이상 속성으로 이루어진 경우 부분함수 종속성 제거

조건:

  • 1정규화를 만족해야 함
  • 모든 비주요 속성이 기본키 전체에 완전 함수 종속되어야 함
  • 부분 함수 종속(Partial Functional Dependency) 제거

부분 함수 종속이란? 복합키의 일부 속성에만 종속되는 경우를 의미합니다.

적용 전 예시:

수강 테이블
-----------
학생ID | 과목ID | 학생명 | 교수명 | 성적
---------------------------------------
S001 | C001 | 홍길동 | 김교수 | A
S001 | C002 | 홍길동 | 이교수 | B
S002 | C001 | 김철수 | 김교수 | B
  • 학생명은 학생ID에만 종속 (부분 함수 종속)
  • 교수명은 과목ID에만 종속 (부분 함수 종속)

적용 후 예시:

학생 테이블
-----------
학생ID | 학생명
S001 | 홍길동
S002 | 김철수

과목 테이블
-----------
과목ID | 교수명
C001 | 김교수
C002 | 이교수

수강 테이블
-----------
학생ID | 과목ID | 성적
S001 | C001 | A
S001 | C002 | B
S002 | C001 | B

3정규화 (3NF: Third Normal Form)​

정의: 기본키를 제외한 칼럼간의 이행함수 종속성 제거

조건:

  • 2정규화를 만족해야 함
  • 이행적 함수 종속(Transitive Functional Dependency) 제거
  • 비주요 속성 간의 종속성 제거

이행적 함수 종속이란? A → B이고 B → C일 때, A → C가 성립하는 간접적인 종속 관계를 의미합니다.

적용 전 예시:

사원 테이블
-----------
사원ID | 사원명 | 부서코드 | 부서명 | 부서위치
---------------------------------------------
E001 | 홍길동 | D01 | 영업부 | 서울
E002 | 김철수 | D02 | 개발부 | 판교
E003 | 이영희 | D01 | 영업부 | 서울
  • 사원ID → 부서코드 → 부서명 (이행적 종속)
  • 사원ID → 부서코드 → 부서위치 (이행적 종속)

적용 후 예시:

사원 테이블
-----------
사원ID | 사원명 | 부서코드
E001 | 홍길동 | D01
E002 | 김철수 | D02
E003 | 이영희 | D01

부서 테이블
-----------
부서코드 | 부서명 | 부서위치
D01 | 영업부 | 서울
D02 | 개발부 | 판교

BCNF (Boyce-Codd Normal Form)​

정의: 기본키를 제외하고 후보키가 있는 경우, 후보키가 기본키를 종속함

조건:

  • 3정규화를 만족해야 함
  • 모든 결정자(Determinant)가 후보키(Candidate Key)여야 함
  • 일반 속성이 후보키를 결정하는 경우 제거

적용 전 예시:

수업 배정 테이블
-----------
학생ID | 과목명 | 교수명
S001 | 데이터베이스 | 김교수
S001 | 알고리즘 | 이교수
S002 | 데이터베이스 | 김교수
  • (학생ID, 과목명)이 기본키
  • 하지만 교수명 → 과목명 종속 관계 존재 (한 교수는 한 과목만 담당)

적용 후 예시:

수업 배정 테이블
-----------
학생ID | 교수명
S001 | 김교수
S001 | 이교수
S002 | 김교수

교수-과목 테이블
-----------
교수명 | 과목명
김교수 | 데이터베이스
이교수 | 알고리즘

4정규화 (4NF: Fourth Normal Form)​

정의: 여러칼럼(또는 하나의 칼럼)을 중복시키는 경우 분해하여 다중값 종속성을 제거

조건:

  • BCNF를 만족해야 함
  • 다중값 종속(Multi-Valued Dependency) 제거
  • 독립적인 다중값 속성 분리

다중값 종속이란? 한 속성의 값이 다른 속성의 여러 값과 독립적으로 연결되는 경우를 의미합니다.

적용 전 예시:

교수 테이블
-----------
교수ID | 담당과목 | 연구분야
P001 | 데이터베이스 | 인공지능
P001 | 데이터베이스 | 빅데이터
P001 | 알고리즘 | 인공지능
P001 | 알고리즘 | 빅데이터
  • 담당과목과 연구분야가 독립적으로 다중값 관계

적용 후 예시:

교수-과목 테이블
-----------
교수ID | 담당과목
P001 | 데이터베이스
P001 | 알고리즘

교수-연구분야 테이블
-----------
교수ID | 연구분야
P001 | 인공지능
P001 | 빅데이터

추가 설명:

  • 다중값 종속 A ↠ B, A ↠ C가 있고 B와 C가 서로 독립적이면, 스키마 A(B C)는 4NF 위배
  • 이때 A-B, A-C 두 관계로 분해하면 무손실 분해가 가능하며 중복이 제거됨

설계 팁:

  • 설문, 취미, 기술스택 등 독립 다중값 속성은 별도 교차 테이블로 분리
  • 다중값 속성 간 상호 제약이 있는지(독립성 위배)를 먼저 확인

5정규화 (5NF: Fifth Normal Form)​

정의: 관계가 세 개 이상의 하위 관계로 조인될 때만 원래 관계가 복원되는 조인 종속(Join Dependency)을 만족하면, 해당 조인 종속을 기반으로 무손실 분해

조건:

  • 4정규화를 만족해야 함
  • 모든 유효한 조인 종속이 후보키에 의해 내재적으로 보장되지 않음
  • 조인 종속을 만족하도록 분해해도 정보 손실이 없고, 중복이 더 이상 감소하지 않는 상태

조인 종속이란? 관계 R이 R1, R2, ..., Rn으로 분해되어 R = R1 ⨝ R2 ⨝ ... ⨝ Rn 이 항상 성립하는 경우를 의미합니다.

적용 전 예시:

공급(공급업체, 부품, 프로젝트)
------------------------------
S1 | P1 | J1
S1 | P2 | J1
S1 | P1 | J2
S2 | P1 | J1
  • 비즈니스 규칙:
    1. 공급업체-부품 허용 쌍이 존재
    2. 공급업체-프로젝트 허용 쌍이 존재
    3. 부품-프로젝트 허용 쌍이 존재
  • 세 쌍이 모두 허용되면 (공급업체, 부품, 프로젝트) 삼자 관계가 성립
  • 원본 테이블은 이 조합들 때문에 중복과 삽입/삭제 이상이 발생 가능

적용 후 예시(무손실 분해):

공급업체_부품(공급업체, 부품)
-------------------------
S1 | P1
S1 | P2
S2 | P1

공급업체_프로젝트(공급업체, 프로젝트)
-------------------------------
S1 | J1
S1 | J2
S2 | J1

부품_프로젝트(부품, 프로젝트)
-------------------------
P1 | J1
P1 | J2
P2 | J1
  • 세 관계를 조인하면 원래의 공급(공급업체, 부품, 프로젝트)을 정확히 복원
  • 각 이항 관계 단위로 관리되어 중복 감소, 이상 현상 완화

주의사항:

  • 5NF는 실무에서 빈도는 낮으나, 다:다:다 구조에서 중요한 무결성 이슈를 해결
  • 세(또는 그 이상) 관계의 조합이 의미적으로 독립 조건을 충족하는지 반드시 검증

함수적 종속성 (Functional Dependency)​

X가 Y를 결정한다, Y는 X에 함수적으로 종속된다​

표기법: X → Y

의미:

  • X 값이 결정되면 Y 값이 유일하게 결정됨
  • X는 결정자(Determinant), Y는 종속자(Dependent)

함수적 종속성의 유형​

1. 부분함수 종속성 (Partial Functional Dependency)​

기본 키가 두 개 이상이 있는 경우, 일반 속성이 두 개 중 하나의 키에 함수적으로 종속되는 경우

예시: (학생ID, 과목ID) → 학생명
학생ID → 학생명 (부분 함수 종속)

2. 이행함수 종속성 (Transitive Functional Dependency)​

기본키를 제외한 컬럼 간의 함수적 종속성 (일반 속성 간의 종속)

예시: 사원ID → 부서코드 → 부서명
사원ID → 부서명 (이행적 종속)

3. BCNF​

일반속성이 특정키 중 하나를 종속시킬 때 (특정키 중 하나가 일반속성에 종속될 때)

예시: 교수명 → 과목명
(학생ID, 과목명)이 기본키인데, 교수명(일반 속성)이 과목명(키의 일부)을 결정

정규화의 장단점​

장점​

  1. 데이터 중복 최소화

    • 저장 공간 절약
    • 일관성 유지 용이
  2. 데이터 무결성 향상

    • 이상 현상 방지
    • 참조 무결성 보장
  3. 유지보수 효율성

    • 데이터 수정 시 한 곳만 변경
    • 확장성 증대
  4. 논리적 명확성

    • 직관적인 데이터 구조
    • 이해하기 쉬운 모델

단점​

  1. 조인 연산 증가

    • 쿼리 복잡도 증가
    • 성능 저하 가능성
  2. 개발 복잡도 증가

    • 테이블 수 증가
    • 관계 관리 복잡
  3. 쿼리 성능 저하

    • 여러 테이블 조인 필요
    • 응답 시간 증가 가능

역정규화 (Denormalization)​

정규화된 데이터베이스에서 성능 향상을 위해 의도적으로 중복을 허용하는 기법입니다.

역정규화가 필요한 경우​

  1. 성능 개선

    • 조인 연산이 과도하게 많은 경우
    • 응답 시간이 중요한 조회 작업
    • 대용량 데이터 처리
  2. 계산 속성

    • 합계, 평균 등 집계 값
    • 자주 계산되는 파생 속성
  3. 이력 관리

    • 특정 시점의 데이터 스냅샷
    • 감사 추적(Audit Trail)

역정규화 기법​

1. 테이블 통합​

-- 정규화된 구조
CREATE TABLE 주문 (주문ID, 고객ID, 주문일자);
CREATE TABLE 고객 (고객ID, 고객명, 연락처);

-- 역정규화 (빈번한 조회를 위해)
CREATE TABLE 주문 (
주문ID,
고객ID,
고객명, -- 중복 허용
연락처, -- 중복 허용
주문일자
);

2. 파생 컬럼 추가​

CREATE TABLE 주문 (
주문ID,
고객ID,
주문금액,
할인금액,
최종금액 -- 계산 컬럼 (주문금액 - 할인금액)
);

3. 중복 테이블 생성​

-- 원본 테이블 (정규화)
CREATE TABLE 거래내역 (...);

-- 집계 테이블 (역정규화)
CREATE TABLE 월별거래집계 (
년월,
총거래건수,
총거래금액,
평균거래금액
);

역정규화 시 주의사항​

  1. 데이터 무결성 관리

    • 트리거 또는 애플리케이션 로직으로 동기화
    • 정기적인 데이터 검증
  2. 변경 관리

    • 중복 데이터의 일관성 유지 방안 마련
    • 명확한 갱신 규칙 정의
  3. 성능 측정

    • 실제 성능 개선 효과 검증
    • 모니터링 체계 구축

정규화 Best Practices​

1. 적절한 정규화 수준 선택​

  • OLTP 시스템: 3정규화까지 적용 권장
  • OLAP 시스템: 선택적 역정규화 고려
  • 하이브리드: 용도에 따라 분리 설계

2. 성능과 무결성의 균형​

정규화 수준    무결성    성능    복잡도
-------------------------------------------
1NF 낮음 높음 낮음
2NF 중간 중간 중간
3NF 높음 낮음 높음
BCNF 매우높음 매우낮음 매우높음

3. 단계적 접근​

  1. 처음엔 3정규화까지 진행
  2. 성능 테스트 수행
  3. 필요시 선택적 역정규화
  4. 지속적인 모니터링 및 개선

4. 문서화​

  • 정규화 수준과 이유 명시
  • 역정규화된 부분 명확히 표시
  • 데이터 동기화 방법 문서화

교수기 과련번호를 결정​

정규화 과정에서 자주 발생하는 실수와 해결 방법입니다.

고수기 1: 과도한 정규화​

문제점:

  • 필요 이상의 테이블 분리
  • 과도한 조인으로 성능 저하

해결책:

  • 비즈니스 요구사항 우선 고려
  • 성능 테스트 기반 의사결정

고수기 2: 불충분한 정규화​

문제점:

  • 데이터 중복 발생
  • 이상 현상으로 데이터 무결성 훼손

해결책:

  • 최소 3정규화 적용
  • 함수적 종속성 철저히 분석

고수기 3: 식별자 설계 오류​

문제점:

  • 자연키 사용으로 인한 복잡도 증가
  • 복합키의 과도한 전파

해결책:

  • 대리키(Surrogate Key) 활용
  • 비즈니스 키와 기술 키 분리

학림(PK1), 과목번호(PK2), 교수​

정규화 과정에서 키 관리는 매우 중요합니다.

주식별자 (Primary Key) 관리​

특징:

  • 유일성(Uniqueness) 보장
  • NOT NULL 제약
  • 변경 불가능성(Immutability) 권장

예시:

CREATE TABLE 수강 (
학번 VARCHAR(10), -- PK1
과목번호 VARCHAR(10), -- PK2
교수 VARCHAR(50),
성적 CHAR(1),
PRIMARY KEY (학번, 과목번호)
);

복합키 설계 시 고려사항​

  1. 키의 크기

    • 가능한 한 작게 유지
    • 인덱스 크기 영향 고려
  2. 의미적 명확성

    • 비즈니스 의미를 가진 키 선택
    • 자연스러운 조합
  3. 확장성

    • 미래 요구사항 변화 대비
    • 유연한 구조 설계

실무 적용 사례​

사례 1: 전자상거래 시스템​

-- 3정규화 적용
CREATE TABLE 고객 (
고객ID VARCHAR(10) PRIMARY KEY,
고객명 VARCHAR(50),
이메일 VARCHAR(100)
);

CREATE TABLE 주문 (
주문ID VARCHAR(10) PRIMARY KEY,
고객ID VARCHAR(10),
주문일자 DATE,
배송주소 VARCHAR(200),
FOREIGN KEY (고객ID) REFERENCES 고객(고객ID)
);

CREATE TABLE 주문상세 (
주문ID VARCHAR(10),
상품ID VARCHAR(10),
수량 INT,
단가 DECIMAL(10,2),
PRIMARY KEY (주문ID, 상품ID),
FOREIGN KEY (주문ID) REFERENCES 주문(주문ID),
FOREIGN KEY (상품ID) REFERENCES 상품(상품ID)
);

-- 선택적 역정규화 (성능을 위해)
ALTER TABLE 주문 ADD COLUMN 주문총액 DECIMAL(12,2);
-- 트리거로 자동 계산 및 동기화

사례 2: 인사관리 시스템​

-- 정규화된 구조
CREATE TABLE 사원 (
사원ID VARCHAR(10) PRIMARY KEY,
사원명 VARCHAR(50),
부서ID VARCHAR(10),
직급ID VARCHAR(10)
);

CREATE TABLE 부서 (
부서ID VARCHAR(10) PRIMARY KEY,
부서명 VARCHAR(50),
상위부서ID VARCHAR(10)
);

CREATE TABLE 직급 (
직급ID VARCHAR(10) PRIMARY KEY,
직급명 VARCHAR(50),
기본급 DECIMAL(10,2)
);

-- 역정규화 (빈번한 조회를 위해)
CREATE VIEW 사원상세정보 AS
SELECT
s.사원ID,
s.사원명,
d.부서명,
j.직급명,
j.기본급
FROM 사원 s
JOIN 부서 d ON s.부서ID = d.부서ID
JOIN 직급 j ON s.직급ID = j.직급ID;

관련 개념​