ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [5] 데이터베이스 논리적 모델링2 - 정규화
    프로젝트/대출금 상환 프로젝트 2026. 6. 6. 16:11

    개요 

     

    데이터베이스를 설계할 때 테이블을 어떻게 나눌지 고민한 경험이 있을 것입니다.

    감각적으로 "이건 따로 빼야 할 것 같은데"라는 판단을 한 적도 있을 것입니다.

    정규화는 그 판단을 이론적으로 뒷받침해주는 도구입니다.

    정규화란 무엇인가

    정규화(Normalization)는 데이터의 중복을 최소화하고 일관성을 보장하기 위해, 테이블을 정규형(Normal Form)이라는 규칙에 맞게 변환하는 과정입니다.

    핵심 개념은 **함수 종속성(Functional Dependency)**입니다. X → Y로 표기하며, "X 값이 Y 값을 유일하게 결정한다"는 의미입니다. 정규화는 이 종속 관계를 분석해서 잘못된 구조를 찾아내고 테이블을 올바르게 분리하는 작업입니다.

    왜 필요한가

    정규화를 적용하지 않으면 세 가지 이상 현상(Anomaly)이 발생합니다.

    • 갱신 이상: 동일한 데이터가 여러 행에 중복 저장되어 있을 때, 하나만 수정하면 데이터 불일치가 생깁니다.
    • 삽입 이상: 특정 데이터가 없으면 다른 데이터도 저장할 수 없는 구조가 만들어집니다.
    • 삭제 이상: 하나의 행을 삭제했을 때 의도치 않게 다른 정보까지 사라집니다.

    이를 해결하기 위해 단계별로 정규형을 적용합니다. 실무에서는 보통 3NF 또는 BCNF까지 적용하는 것을 목표로 합니다.

    이 글의 목적

    이번 포스팅에서는 제가 설계한 대출금 상환 테이블을 대상으로 직접 정규화를 적용해봤습니다.

    이론만 아는 것과, 실제 설계에 대입해 "이 테이블은 왜 이렇게 나눴는가"를 설명할 수 있는 것은 다릅니다.

    각 정규형 단계별로 설계가 조건을 만족하는지 체크하고 그 근거를 정리합니다.

     

    대상 테이블 요약 

     


    제1 정규형(1NF) 체크

     

    1NF 란

    1NF 의 조건은 테이블의 모든 컬럼잉 원자적인 값을 가져야 한다는 것 입니다. 

    원자적이라는 것은 더 이상 쪼갤 수 없는 단일 값을 의미합니다. 

    하나의 컬럼에 여러 값을 쉼표로 구분해 넣거나, 중첩된 구조로 저장하는 경우가 대표적인 위반 사례 입니다. 

    체크 결과 

    모든 컬럼이 단일 값을 가집니다.

    상환스케줄의 상환금(원금,이자)는 표기상 하나의 컬럼처럼 보이지만 , 실제 테이블에서는 원금과 이자를 별도 컬럼으로 분리합니다. 하나의 컬럼에 두 값을 묶어 저장하지 않습니다. 

     

    반복 그룹이 없습니다.

    대출계약 한 건에 상환 스케줄이 여러 개 연결될 수 있지만 , 이를 대출계약 테이블 내에 배열처럼 저장하지 않습니다. 

    상환 스케줄을 별도 테이블로 분리하고 FK 로 참조하는 구조입니다. 

     

    코드성 값을 별도 테이블로 분리합니다.

    상태명을 문자열로 직접 컬럼에 저장하게 되면, 이는 경우에 따라 원자성 위반으로 이어질 수 있습니다. 

    하지만 이자종류, 상환방법, 대출상태, 상환상태, 연체상태를 각각 독립적인 테이블로 분리하고 이를 FK 로 참조하는 구조를 유지하여 이를 예방합니다.

    결론

    14개 테이블 모두 1NF를 만족합니다.


    제2 정규형(2NF) 체크

     

    2NF 란

     

    2NF의 조건은 두 가지입니다.

    1NF를 만족해야 하고, 모든 컬럼이 기본 키 전체에 대해 완전 함수 종속이어야 합니다.

    즉, 복합 PK의 일부에만 종속되는 컬럼이 있으면 안 됩니다.

    이를 부분 함수 종속이라고 하며, 2NF는 이를 제거하는 과정입니다.

    체크 결과 

    부분 함수 종속은 복합 PK가 존재할 때만 발생할 수 있습니다.

    전체 14개 테이블을 확인한 결과, 모든 테이블이 자연키 대신 단일 대리키를 PK로 사용하고 있습니다.

    복합 PK가 없으므로 부분 함수 종속이 발생할 수 없는 구조입니다.

    결론

    14개 테이블 모두 2NF를 만족합니다.


    제3 정규형 (3NF) 체크

     

    3NF란

    3NF의 조건은 두 가지입니다.

    2NF를 만족해야 하고, 이행적 함수 종속이 없어야 합니다.

    이행적 함수 종속이란 PK → 일반 컬럼A → 일반 컬럼B 형태로, 기본 키가 아닌 일반 컬럼이 다른 일반 컬럼을 결정하는 관계를 의미합니다.

    체크 결과

    이행적 종속이 발생할 수 있는 후보를 중심으로 확인했습니다.

     

    상환스케줄의 적용금리 가 검토 대상입니다.

    스케줄id → 대출계좌id → 계약id → 상품id → 가산금리 같은 체인이 성립한다면 이행적 종속으로 볼 수 있습니다.

    그러나 적용금리는 대출상품의 가산금리를 그대로 참조하는 것이 아니라, 스케줄 생성 시점에 확정된 금리를 스냅샷으로 저장한 값입니다. 즉, 스케줄id → 적용금리로 직접 종속되는 독립적인 컬럼이므로 이행적 종속이 아닙니다.

     

    상환이력의 연체id FK 도 검토 대상입니다. 연체가 발생한 경우에만 연체이력을 참조하고, 연체가 없으면 NULL을 허용하는 구조입니다. 연체이력의 속성들이 상환이력 내에 중복 저장되지 않고 FK 참조로만 연결되어 있으므로 이행적 종속이 발생하지 않습니다.

     

    그 외 나머지 테이블들도 일반 컬럼이 다른 일반 컬럼을 결정하는 관계가 없습니다. FK 컬럼은 모두 참조 역할만 하며, 각 테이블의 컬럼들은 PK에만 직접 종속됩니다.

     

    결론

    14개 테이블 모두 3NF를 만족합니다.


    BCNF 체크

     

    BCNF란

    BCNF는 3NF를 강화한 버전으로, 모든 결정자가 후보 키 여야 한다는 조건입니다.

    후보 키란 행을 유일하게 식별할 수 있는 컬럼으로, PK뿐 아니라 UQ 제약이 걸린 컬럼도 포함됩니다.

    3NF를 만족하더라도 후보 키가 아닌 일반 컬럼이 다른 컬럼을 결정하는 관계가 있다면 BCNF를 위반합니다.

    체크 결과

    BCNF 위반 여부는 UQ 컬럼이 다른 일반 컬럼을 결정하는 관계가 있는지를 중심으로 확인했습니다.

    UQ 제약이 걸린 컬럼은 회원의 로그인id, 주계좌의 계좌번호, 대출계좌의 계좌번호, 코드성 테이블들의 상태명/방법명입니다.

    이 컬럼들은 모두 행을 유일하게 식별하는 후보 키 역할을 하며, 다른 일반 컬럼을 결정하는 관계가 없습니다.

    즉 모든 결정자가 후보 키이므로 BCNF 조건을 만족합니다.

     

    결론

    14개 테이블 모두 BCNF를 만족합니다.

     


    마무리

     

    1NF부터 BCNF까지 전체 14개 테이블을 체크한 결과, 모든 테이블이 각 정규형의 조건을 만족했습니다.

    처음부터 단일 대리키를 PK로 사용하고, 코드성 데이터를 별도 테이블로 분리하며, 반복 그룹 없이 FK 참조 구조를 일관되게 적용한 것이 정규화 조건을 자연스럽게 충족한 배경입니다.

     

    다음 글에서는 논리적으로 올바른 이 설계를 MySQL에 최적화된 형태로 구현하는 물리적 모델링을 진행합니다.

    데이터 타입 선정, 인덱스 설계 , 제약 조건 설정 등을 다룰 것 입니다. 

     

Designed by Tistory.