Intro
여러 데이터베이스를 다룰 때, 스키마를 설계하는 것은 중요한 요소다. 최근에도 ORM 을 설계할 때, 정규화를 무시한 경우도 있었다. 이에 대해 보다 자세히 다뤄보기 위해 위 글을 작성한다.
🟢 정규화(Normalization)
데이터베이스 정규화(Normalization)는 데이터베이스 설계를 최적화하기 위해 데이터를 구조화하는 과정이다. 이 과정은 테이블 간에 데이터의 중복을 최소화하고, 데이터 무결성(Integrity)을 유지하기 위해 실시하며, 데이터베이스의 저장 용량 또한 줄일 수 있다. 정규화를 통해 데이터 모델의 일관성을 유지하고, 업데이트 시 발생할 수 있는 오류를 줄일 수 있다. 일반적으로 여러 단계의 정규형이 있으며, 각 단계는 특정한 이상 현상을 제거하는 데 중점을 둔다.
정규형
릴레이션이 정규화된 정도를 의미한다. 각 정규형마다 제약 조건이 존재하는데 정규형의 차수가 높아질수록 요구되는 제약 조건이 많아지고 엄격해진다. 즉, 테이블을 어떻게 분해되는지에 따라 정규화 단계가 달라지는데, 정규화는 구성 방법이기 때문에 해당 방법을 진행하는 규칙같은 것이 존재하고 이를 정규형이라고 한다.
✅ 1NF(제1정규형)
모든 컬럼의 값이 원자값(더 이상 분할이 불가능한 값) 이어야 한다.
🔻 [정규화 전]
주문ID |
고객명 |
상품명 |
1 |
홍길동 |
TV,세탁기 |
주문 데이터베이스를 예시로 들어보자. 한 행에 여러 상품명이나 수량이 들어가 있는 경우, 각 행에 하나의 상품만을 나타내도록 분리한다.
🔻 [정규화 후]
주문ID |
고객명 |
상품명 |
1 |
홍길동 |
TV |
1 |
홍길동 |
세탁기 |
상품명의 TV,세탁기를 각각의 행으로 분리한다.
✅ 2NF(제2정규형)
제2정규형(2NF)의 목적은 부분 함수 종속성을 제거하는 것이다. 부분 함수 종속성이란 복합 키(두 개 이상의 컬럼으로 구성된 키) 를 가진 테이블에서, 키가 아닌 속성이 키의 일부분에만 종속되는 경우를 말한다. 즉, 모든 비키 속성이 기본 키 전체에 대해 함수적으로 종속되어야 한다.
🔻 [정규화 전]
주문ID |
상품ID |
고객명 |
수량 |
1 |
A01 |
홍길동 |
2 |
1 |
A02 |
홍길동 |
1 |
2 |
A01 |
김철수 |
3 |
고객이 여러 개의 주문을 할 수 있는 데이터베이스에서, 주문 ID 와 상품 ID 를 복합 키로 사용하는 주문 테이블이 있다고 가정해보자. 여기서 '고객명'은 '주문ID' 에 종속적이지만 '상품ID' 와는 관련이 없다. 즉, 주문 ID 를 통해 고객명을 알 수 있지만 상품 ID 를 통해 고객명을 알 순 없다는 의미이다. 따라서 이 테이블은 2NF 를 만족하지 않는다.
🔻 [정규화 후]
주문 테이블
주문ID |
상품ID |
수량 |
1 |
A01 |
2 |
1 |
A02 |
1 |
2 |
A01 |
3 |
고객 테이블
✅ 3NF(제3정규형)
제3정규형의 목적은 이행적 함수 종속성을 제거하는 것이다. 이행적 함수 종속성이란 한 속성이 다른 속성에 간접적으로 종속되는 경우를 말한다. 예를 들어 A 는 B, B 는 C 를 만족할 때, A 는 C 가 성립되는 것을 의미한다. 이 성질을 제거해야 한다.
🔻 [정규화 전]
상품ID |
제조사 |
본사 위치 |
A01 |
삼성 |
수원 |
A02 |
LG |
평택 |
상품 정보를 저장하는 테이블에서, 상품ID 에 따라 제조사가 결정되고, 제조사에 따라 본사 위치가 결정된다고 가정해보자. 여기서'본사 위치'는 '제조사'에 의해 간접적으로 결정되므로, '상품ID' 에 직접적으로 종속되지 않는다. 그러므로 이 테이블은 3NF 를 만족하지 않는다.
이를 3NF 로 만들기 위해, 제조사와 본사 위치를 분리할 수 있다.
🔻 [정규화 후]
상품 테이블
제조사 테이블
여기까지 개념을 공부하면서 함수 종속성에 대한 완벽한 이해가 되지 않아 추가로 개념에 대해 찾아봤다.
✳️ 함수 종속성 (Functional Dependency)
'데이터베이스의 릴레이션 R(테이블)에서 X 와 Y 를 R 의 부분집합이라고 할 때, X의 값 각각에 대해 Y의 값이 오직 하나로 결정될 때, Y 는 X에 종속된다고 한다.'
위의 개념이 위키백과에 정의된 개념이다. 간단히 설명하면 테이블의 한 필드값(X)이 다른 필드값(Y)을 결정하는 관계를 함수 종속이라고 할 수 있고, 이는 우리가 중,고등학교 시절에 배운 y = f(x) 의 관계와 같다. 이때 X 를 결정자라고 하며 Y 를 종속자라고 한다.
정규화가 잘된 테이블일수록 결정자 X 는 PK 하나에 종속자가 여러개인 구조를 가진다.
위처럼 X 가 다른 모든 필드 값을 결정하는 X->Y1, X->Y2, X->Y3 와 같은 관계를 띄게 된다. 이 성격을 완전 함수 종속이라고도 한다.
완전 함수 종속
종속자가 기본키에만 종속되며, 기본키가 여러 속성으로 구성되어 있을 경우, 기본 키를 구성하는 모든 속성이 포함된 기본 키의 부분집합에 종속된 경우를 완전 함수 종속이라고 한다.
주민번호 |
이름 |
성별 |
주소 |
910211-1****** |
이미자 |
남 |
서울 |
960306-1****** |
고도리 |
남 |
서울 |
939515-2****** |
고도리 |
여 |
인천 |
위의 테이블을 예시로, 주민번호를 알면 이름/성별/주소를 모두 식별할 수 있다. 하지만 이름은 어떤 것도 식별할 수 없고, 이름의 경우 같은 이름에 다른 성별과 다른 주소, 다른 주민번호를 가질 수 있다. 즉, 이름으로 다른 속성을 결정할 수 없다. 이러한 원리를 적용해보면 주민번호를 제외한 그 어떤 속성도 다른 속성을 결정할 수 없다.
그렇기 때문에 주민번호를 제외한 다른 속성들이 다른 속성에 종속되지 않는 완전 함수 종속이 이루어진 테이블이다.
*️⃣ 글을 마치며
데이터의 중복 속성을 제거하기 위해 정규화를 진행하지만 테이블이 늘어나다보니 성능의 저하가 떨어질 수 있다. (릴레이션 분해로 인해 릴레이션 간의 연산(JOIN) 이 많아져서 응답 시간이 느려질 수 있다.) 그렇기에 적절한 정규화 대상을 선별하고 그 외엔 부분 적인 반정규화를 해야 한다.
온라인 거래 시스템과 같은 CRUD 가 빈번하게 일어발생하는 데이터베이스는 정규화하는 것이 좋으며, 분석 리포트와 같은 조회, 분석이 위주인 데이터베이스는 연산의 속도를 위해 반정규화의 대상이 된다.
💡 반정규화
정규화된 시스템을 성능 향상 및 개발과 운영의 단순화를 위해 역으로 정규화를 수행하는 것을 말한다. 일반적으로 join 을 많이 사용해야 할 경우, 대량의 범위를 자주 처리해야 하는 경우 등 조회에 대한 처리가 중요하다고 판단될 때 부분적으로 반정규화를 해야 한다.