본문 바로가기
● Data Processing

정규화 단계별 실전 예제와 최적화 팁

by DataFolio.lab 2026. 5. 24.
반응형

데이터베이스 정규화(Database Normalization)는 관계형 데이터 설계의 근간으로, 데이터 중복을 줄이고 무결성을 보장하며 삽입·갱신·삭제 이상을 방지하기 위한 체계적인 분해 과정을 말합니다. 많은 조직이 OLTP 시스템에서 안정적인 트랜잭션 무결성을 원하지만, 한편으로는 분석(Analytics)과 리포팅에서 성능을 확보해야 하므로 정규화와 역정규화(denormalization)의 균형을 맞추는 일이 필수적입니다. 이 글에서는 핵심 개념, 정규형 단계, 함수적 종속성 분석 방법, 실무 적용 가이드라인, OLTP·OLAP 관점에서의 모범 사례와 함께 구체적인 설계 절차를 제시합니다. 

정규화 단계별 실전 예제와 최적화 팁

반응형

왜 정규화가 중요한가

정규화의 목적은 데이터 중복을 제거하고 데이터 일관성(consistency)과 무결성(integrity)을 보장하는 것입니다. 중복이 많은 테이블은 저장공간을 낭비할 뿐 아니라, 동일한 정보가 여러 행에 존재할 때 갱신 이상(update anomaly)이 발생하여 데이터 불일치가 생길 수 있습니다. 또한 삽입 이상(insert anomaly)이나 삭제 이상(delete anomaly)으로 인해 실제로 필요한 정보를 추가하거나 제거할 수 없는 상황이 발생할 수 있습니다. 따라서 실무에서는 정규화를 통해 이러한 이상을 구조적으로 제거하고, 스키마 변경 시 비용을 줄이는 것이 우선 목표가 됩니다. 


핵심 개념: 함수적 종속성과 이상 유형

정규화를 이해하려면 함수적 종속(functional dependency, FD)을 정확히 파악해야 합니다. FD는 어떤 속성 집합 A가 속성 B의 값을 결정하는 관계로, A → B로 표기합니다. 후보키(candidate key)와 기본키(primary key)은 특별한 결정자 역할을 하며, FD 분석을 통해 어떤 속성이 어떤 키에 의존하는지를 파악합니다. 부분 종속(partial dependency)은 복합키의 일부만으로 비키 속성이 결정되는 경우로 2NF 위반 원인이 되고, 이행 종속(transitive dependency)은 A → B, B → C이면 A → C로 전개되는 구조로 3NF 위반의 원인입니다. 다치 종속(multi-valued dependency)은 한 속성이 여러 독립적 다중값을 갖는 경우로 4NF에서 다룹니다. 이들 종속성을 정확히 식별하면 어느 속성을 분리하고 어떤 관계를 유지해야 할지 결정할 수 있습니다. 


정규형 단계별 정의와 실무 예제

다음은 각 정규형의 정의와 실무에서의 적용 전·후 예시입니다.

  • 제1정규형(1NF): 모든 속성은 원자값을 가져야 합니다. 반복 그룹이나 배열은 허용되지 않습니다. 예: 고객의 취미가 복수일 경우 Customer_Hobby 테이블로 분리합니다.
  • 제2정규형(2NF): 1NF를 만족하고, 복합키가 아닌 비키 속성은 기본키 전체에 완전 종속해야 합니다(부분 종속 제거). 예: 주문(Order) 테이블에서 제품명(product_name)이 복합키의 일부에만 의존하면 제품 테이블로 분리합니다.
  • 제3정규형(3NF): 2NF를 만족하고 비키 속성 간의 이행 종속을 제거합니다. 모든 비키 속성은 기본키에 직접 의존해야 합니다. 예: 주소 테이블에서 우편번호 → 시도 정보로의 이행이 있으면 별도 코드 테이블로 분리합니다.
  • BCNF(Boyce-Codd Normal Form): 모든 결정자는 후보키여야 합니다. 3NF보다 엄격하며 드문 케이스에서 추가 분해가 필요합니다.
  • 4NF: BCNF를 만족하며, 독립적인 다치 종속을 제거합니다. 예: 한 테이블에 제품의 색상과 사이즈가 독립적으로 다중값으로 존재하면 두 테이블로 나눕니다.
  • 5NF: 조인 종속(join dependency)을 제거하여 조인으로만 재구성 가능한 복잡한 결합을 개별 릴레이션으로 분해합니다. 실무에서는 적용 빈도가 낮습니다.

실무 예제(요약):

  • 원본 Orders(order_id, customer_name, customer_address, product_id, product_name, qty)
  • 정규화 후:
    • Customers(customer_id, name, address)
    • Products(product_id, name)
    • Orders(order_id, customer_id, order_date)
    • OrderItems(order_id, product_id, qty)

이 구조는 주문과 제품의 다대다 관계를 적절히 모델링하고 중복을 제거합니다. 


정규화의 장단점과 트레이드오프

정규화의 장점은 저장공간 절감, 데이터 정합성 향상, 이상 현상 방지, 유지보수 용이성 등입니다. 반면 단점은 분해로 인해 조인(join) 횟수가 늘어나 조회 성능이 저하될 수 있다는 점입니다. 특히 대용량 분석이나 리포팅 워크로드에서는 정규화된 스키마가 불리할 수 있어 의도적인 역정규화가 필요합니다. 실무에서는 OLTP 시스템에서는 3NF/BCNF 수준의 정규화를 유지하고, OLAP이나 BI(예: Power BI) 레이어에서는 스타 스키마(star schema)와 같은 차원 모델로 역정규화하는 방식이 일반적입니다. 


OLTP와 OLAP에서의 적용 지침

  • OLTP: 트랜잭션 무결성이 중요하므로 3NF 또는 BCNF 수준의 정규화 권장. 인덱스와 제약조건을 이용해 데이터 무결성을 강화합니다.
  • OLAP/BI: 대량의 읽기·집계 작업이 많아 조인을 줄이고 쿼리 성능을 높이기 위해 스타 스키마나 스노우플레이크(snowflake) 모델을 사용합니다. 사실 테이블(fact table)에 측정값을 두고, 차원 테이블(dimension table)은 분석 편의를 위해 역정규화될 수 있습니다. ETL/ELT 파이프라인에서 원천 정규화 상태를 파악한 뒤 차원 모델을 생성합니다.

실무 설계 절차(단계별 체크리스트)

  1. 요구사항 수집: 읽기/쓰기 패턴, 동시성, 성능 SLA를 문서화합니다.
  2. 도메인 속성 목록화: 모든 엔티티와 속성 리스트를 작성하고 후보키를 식별합니다.
  3. 함수적 종속성(FD) 분석: FD 다이어그램을 작성하여 A → B 관계를 명시합니다.
  4. 단계별 정규화 수행: 1NF → 2NF → 3NF(및 필요시 BCNF)로 분해하면서 무손실성(lossless join)과 종속성 보존(dependency preservation)을 검증합니다.
  5. 성능·운영 고려: 조인 비용, 인덱스, 파티셔닝, 캐시 전략을 설계하고, 필요 시 역정규화를 계획합니다.
  6. 테스트 및 마이그레이션: 데이터 마이그레이션 시나리오, 테스트 케이스(무결성/성능), 점진적 롤아웃 전략을 수립합니다.

무손실 분해와 종속 보존 확인 방법

정규화 과정에서 중요한 두 가지 원칙은 무손실 분해(lossless decomposition)와 종속 보존(dependency preservation)입니다. 무손실 분해는 분해한 테이블들을 조인하여 원래 관계를 완전하게 복원할 수 있어야 함을 뜻합니다. 이를 확인하려면 분해한 릴레이션들의 교집합이 후보키를 포함하는지를 확인합니다. 종속 보존은 원래 릴레이션에 존재하던 모든 함수적 종속성이 분해 후에도 검사 가능한지를 의미하며, 일부 고차원 분해에서는 종속 보존을 완전하게 유지하기 어려울 수 있습니다. 실무에서는 무손실성은 필수, 종속 보존은 가능하면 유지하되 필요 시 애플리케이션 차원 또는 트리거로 보완합니다. 


성능 최적화 팁(정규화 상태에서)

  • 빈번한 조인이 예상되는 경우 적절한 인덱스(복합 인덱스 포함)를 설계합니다.
  • 대용량 테이블은 파티셔닝(partitioning)으로 관리해 I/O를 줄입니다.
  • 조회 성능이 핵심이면 읽기 전용 복제본(read replica)이나 컬럼형 저장(columnar storage)을 고려합니다.
  • OLAP 작업은 ETL 단계에서 집계(pre-aggregation)와 요약 테이블(summary table)을 만들어 실시간 쿼리 부담을 줄입니다.

설계 사례: 간단한 주문 시스템(정규화 전→후)

아래는 정규화 전후의 스키마 변환 예시입니다.

  • 정규화 전:
    • Orders(order_id, customer_name, customer_address, product_id, product_name, qty)
  • 정규화 후:
    • Customers(customer_id, name, address)
    • Products(product_id, name)
    • Orders(order_id, customer_id, order_date)
    • OrderItems(order_id, product_id, qty)

이 전환은 고객 정보와 제품 정보를 중복 저장하지 않도록 하고 주문-제품의 다대다 관계를 OrderItems로 명확히 표현합니다. 


권장 도구와 검증 방법

  • ERD 도구: 데이터 모델링 시 ERWin, draw.io, dbdiagram.io 등으로 시각적 모델을 작성합니다.
  • 정규화 검증: FD 목록과 후보키를 문서화하고, 각 단계(1NF→3NF)에서 위배되는 항목을 체크리스트로 관리합니다.
  • 성능 검증: 실제 데이터 샘플로 성능 테스트(쿼리 실행 계획, CPU·I/O 프로파일링)를 수행하고, 필요 시 역정규화 포인트를 선정합니다.

 

반응형

놓치면 아쉬운 추천 글, 함께 읽어보세요!

  • 추천 글을 불러오는 중입니다...