정규화를 이욯해 데이터베이스를 설계하는 방법에 대해 알아보자.
정규화는 데이터베이스를 설계한 후 설계 결과물을 검증하기 위해 사용하기도 한다.
데이터베이스를 잘못 설계하면 불필요한 데이터 중복이 발생하여 릴레이션에 대한 데이터의 삽입, 수정, 삭제 연산을 수행할 때 부작용이 발생할 수 있다. 이러한 부작용을 이상 현상이라 한다.
정규화란 이상 현상을 제거하면서 데이터베이스를 올바르게 설계해나가는 과정이다. 정규화의 필요성과 방법을 구체적으로 알아보기에 앞서 이상 현상을 종류별로 자세히 알아보자.
이상 현상의 종류는 다음과 같다.
이상 유형 | 설명 |
---|---|
삽입 이상 | 새 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제 |
갱신 이상 | 중복 투플 중 일부만 변경하여 데이터가 불일치하게 되는 모순의 문제 |
삭제 이상 | 투플을 삭제하면 꼭 필요한 데이터까지 함께 삭제되는 데이터 손실의 문제 |
삽입 이상(insertion anomaly)
릴레이션에 새 데이터를 삽입하기 위해 원치 않는 불필요한 데이터도 함께 삽입해야 하는 문제를 삽입 이상이라 한다.
예를 들어 다음과 같은 상황이 있을 수 있다.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Rim | BE | Honux |
위 테이블에 새로운 학생을 추가하려고 하는데, 아직 수강하려는 과목과 교수님 정보를 모르는 경우를 가정해 보자. 이런 경우에는 Course 와 Professor 필드에 NULL 값을 넣어야만 한다.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Rim | BE | Honux |
002 | Go | NULL | NULL |
이런 경우 삽입 이상이 발생했다고 볼 수 있다. 왜냐하면 완전한 정보 없이 데이터를 삽입해야 했기 때문이다. 이러한 문제는 데이터베이스 설계가 적절하지 않아 발생하며, 이를 해결하기 위해 보통은 데이터베이스 정규화를 수행합니다.
갱신 이상(update anomaly)
릴레이션의 중복된 투플들 중 일부만 수정하여 데이터가 불일치하게 되는 모순이 발생하는 것을 갱신 이상이라 한다.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Birdie | BE | Honux |
002 | MongNam | BE | Honux |
여기서 교수님 이름이 변경되었다고 가정해보자. 교수님 이름이 Crong으로 변경되었다면 모든 투플을 Crong으로 변경해야 한다. 하지만, 우리가 실수로 하나의 투플만 변경했다면 갱신 이상이 발생한다.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Birdie | BE | Honux |
002 | MongNam | BE | Crong |
이런 문제는 중복 데이터를 제거하고, 데이터베이스를 적절하게 정규화 해야한다.
삭제 이상
릴레이션에서 투플을 삭제하면 꼭 필요한 데이터까지 함께 삭제하여 데이터가 손실되는 연쇄 삭제 현상을 싹제 이상이라 한다.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Birdie | BE | Honux |
002 | MongNam | BE | Honux |
003 | Noah | IOS | JK |
위 테이블에서 Noah 학생이 졸업하여 그의 데이터를 삭제한다고 가정해보자.
StudentId | Name | Course | Professor |
---|---|---|---|
001 | Birdie | BE | Honux |
002 | MongNam | BE | Honux |
그러나 이렇게 하면 JK 교수님에 대한 정보가 완전히 사라진다. 이것이 바로 삭제 이상의 예이다.
이러한 문제는 학생 정보와 과목 정보를 별도의 테이블로 분리함으로써 관리할 수 있다.
위의 릴레이션에서 여러 이상 현상이 발생하는 이유는 무엇일까? 그 이유는 관련이 없는 데이터, 즉 관련 없는 속성들을 하나의 릴레이션에 모아두고 있기 때문이다. 이상 현상이 발생하지 않도록 하려면, 관련 있는 속성들로만 릴레이션을 구성해야 하는데 이를 위해 필요한 것이 정규화이다.
정규화를 수행하려면 먼저 릴레이션을 구성하는 속성들 간의 관련성을 판단할 수 있어야 한다. 정규화 과정에서 고려해야 하는 속성들 간의 관련성을 함수적 종속성이라고 한다.
일반적으로 릴레이션에 함수적 종속성이 하나 존재하도록 정규화를 통해 릴레이션을 분해한다.
하나의 릴레이션을 구성하는 속성들의 부분 집합을 X와 Y라고 할 때, 어느 시점에서든 릴레이션 내의 모든 투플에서 X 값에 대한 Y 값이 항상 하나면 X가 Y를 함수적으로 결정한다 또는 Y가 X에 함수적으로 종속되어 있다 라고 한다.
함수 종속 관계는 X -> Y로 표현하고, X를 결정자, Y를 종속자 라고 한다.
StudentId | Name |
---|---|
001 | Birdie |
002 | MongNam |
위의 릴레이션에서 학생 아이디 값에 대응되는 이름 속성의 값이 단 하나이므로, 학생 아이디가 학생 이름을 결정한다고 볼 수 있다.
StudentId 가 001인 학생의 이름은 Birdie 한 사람 밖에 없다.
그러므로 위 릴레이션에서 학생 이름은 학생 아이디에 함수적으로 종속되어 있어, 학생 아이디는 결정자가 되고, 학생 이름은 종속자가 된다.
위 릴레이션에서 함수 종속 관계는 다음과 같이 기호로 표현할 수 있다.
학생아이디 -> 학생이름
함수적 종속성을 이용하여 릴레이션을 연관성이 있는 속성들로만 구성되도록 분해해서, 이상 현상이 발생하지 않는 올바른 릴레이션으로 만들어나가는 과정을 정규화(normalization)라고 한다. 정규화의 기본 목표는 관련이 없는 함수 종속성을 별개의 릴레이션으로 표현하는 것이다.
정규형은 크게 기본 정규형과 고급 정규형으로 나뉜다. 그러나 실제 데이터베이스 설계에서 대부분의 경우 3정규형 혹은 BCNF까지만 수행하기 때문에 이번에는 BCNF까지만 알아보도록 하자.
릴레이션에 속한 모든 속성의 도메인이 원자 값으로만 구성되어 있으면 제 1 정규형에 속한다.
즉 다중 값을 가지는 속성을 포함한 릴레이션은 제 1정규형의 제약조건을 만족하지 못하므로, 제 1정규형에 속하지 않는다.
이벤트 참여 릴레이션이 제 1정규형에 속하게 하려면, 투플마다 이벤트 번호와 당첨 여부 속성 값을 하나씩만 포함하도록 분해하여, 모든 속성이 원자 값을 가지도록 해야 한다.
제 1정규형에는 속하지만, 불필요한 데이터 중복으로 인해 이상 현상이 발생하는 릴레이션이 있을 수 있다.
이벤트 릴레이션도 제 1정규형을 만족하지만 이상 현상이 발생할 수 있기 때문에 바람직한 릴레이션이라고 할 수 없다.
이벤트 참여 릴레이션이 지닌 특성을 파악하기 위해 함수 종속 관계를 판단해보자.
고객아이디 -> 등급
고객아이디 -> 할인율
고객아이디, 이벤트번호 -> 당첨여부
등급 -> 할인율
이를 다이어그램으로 표현하면 다음과 같다.
이벤트참여 릴레이션에는 등급과 할인율 속성의 값이 중복되어 나타나는 경우가 많다. 이처럼 불필요한 데이터가 중복되면 다음과 같은 삽입, 갱신, 삭제 이상 현상이 발생할 수 있다.
삽입 이상
이벤트참여 릴레이션의 기본키는 {고객아이디, 이벤트번호}이므로, 새 고객에 대한 데이터를 삽입하려면 그 고객이 이벤트에 무조건 참여해야 한다.
갱신 이상
이벤트참여 릴레이션에는 고객아이디가 apple인 고객의 투플이 3개이므로, 이 고객의 등급과 할인율 속성 값이 중복되어 있다. 만약 이 고객의 등급이 gold에서 vip로 변경되면 세 투플의 등급 속성의 값을 vip로 변경해야 한다.
만약 위처럼 일부 투플의 값만 변경하게 된다면, 데이터 일관성을 유지할 수 없게 된다.
삭제 이상
이벤트참여 릴레이션에서 고객아이디가 orange인 고객에 관련된 투플은 단 하나다. 그러므로 이 고객이 E004 이벤트에 참여한 기록을 삭제해달라고 요구하면 이 투플을 삭제해야 한다. 그런데 이 투플을 삭제하면 이벤트와 관련이 없는 데이터, 즉 orange 고객의 등급과 할인율 같은 고객 정보도 함께 삭제되게 된다.
릴레이션이 제 1정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속되면 제 2정규형에 속한다.
제 1정규형에 속하는 릴레이션이 제 2정규형을 만족하게 하려면, 부분 함수 종속을 제거하고 모든 속성이 기본키에 완전 함수 종속되도록 릴레이션을 분해하는 정규화 과정을 거쳐야 한다.
릴레이션이 둘로 분해되면서 등급과 할인율 속성에 대한 데이터 중복이 줄어듦을 확인할 수 있다.
정규화 과정에서 릴레이션을 분해할 때 주의할 점은, 분해된 릴레이션들을 자연 조인하여 분해 전의 릴레이션으로 다시 복원할 수 있어야 한다는 것이다. 즉 릴레이션이 의미상 동등한 릴레이션으로 분해되어야 하고, 릴레이션을 분해했을 때 정보 손실이 발생하지 않아야 한다.
이제 분해된 고객 릴레이션에 발생할 수 있는 이상 현상을 살펴보고, 이러한 이상 현상이 발생하는 이유를 생각해보자.
삽입 이상
새로운 등급과 할인율에 대한 정보는, 해당 등급에 속하는 고객이 있어야 고객 릴레이션에 삽입할 수 있다.
갱신 이상
등급에 대한 할인율이 변경되면 해당 등급에 관련된 모든 투플에서 할인율 속성 값을 똑같이 변경해야 한다.
삭제 이상
고객 탈퇴로 인해 고객 릴레이션에서 투플이 삭제되면 등급과 할인율에 대한 정보까지 삭제된다.
분해된 고객 릴레이션에 여러 이상 현상이 발생하는 이유는, 함수 종속 관계를 여러개 포함하고 있어 결과적으로 이행적 함수 종속이 생기기 때문이다. 릴레이션을 분해하여 이행적 함수 종속을 제거하면, 분해된 릴레이션들은 제 3정규형에 속하게 되고, 앞서 제시한 이상 현상들이 더는 발생하지 않는다.
릴레이션이 제 2정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 이행적 함수 종속이 되지 않으면 제 3정규형에 속한다.
제 3정규형을 살펴보기 전에 이행적 함수 종속에 대해 잠깐 살펴보자.
X -> Y 이고 Y -> Z 이면,
X -> Z 이다.
제 2정규형을 만족하더라도 하나의 릴레이션에 함수 종속 관계가 여러개 존재하고, 논리적으로 이행적 함수 종속 관계가 유도되면 이상 현상이 발생할 수 있다. 릴레이션에서 이행적 함수 종속을 제거해서, 모든 속성이 기본키에 이행적 함수 종속이 되지 않도록 릴레이션을 분해하는 정규화 과정을 거쳐야 제 3정규형을 만족할 수 있다.
릴레이션의 함수 종속 관계에서 모든 결정자가 후보키이면 보이크/코드 정규형에 속한다.
지금까지 살펴본 릴레이션들은 모두 기본키와 후보키를 하나씩 가지고 있었다. 즉 후보키 속성이 하나밖에 없어 이를 기본키로 선정한 경우다. 하지만 실제로는 하나의 릴레이션에서 여러개의 후보키가 존재할 수도 있는데, 이 경우에는 제 3정규형까지 모두 만족하더라도 이상 현상이 발생할 수 있다. 후보키를 여러개 가지고 있는 릴레이션에 발생할 수 있는 이상 현상을 해결하기 위해 제 3정규형보다 좀 더 엄격한 제약조건을 제시한 것이 보이스/코드 정규형이다.
보이스/코드 정규형을 강한 제 3정규형이라고도 한다. 그 이유는 보이스/코드 정규형에 속하는 모든 릴레이션은 제 3정규형에 속하지만, 제 3정규형에 속하는 릴레이션이라고 해서 다 보이스/코드 정규형에 속하는 것은 아니기 떄문이다. 그래서 보이스/코드 정규형이 제 3정규형보다 더 강력한 제약조건을 가지고 있다고 볼 수 있다.
강좌신청 릴레이션에서 기본키인 {고객아이디, 인터넷강좌}가 담당강사번호 속성을 함수적으로 결정하는 것은 당연하다. 그리고 강사 한 명이 인터넷강좌를 하나만 담당하므로 담당강사번호가 인터넷 강좌를 함수적으로 결정한다고 볼 수 있다.
보이스/코드 정규형에 속하지 않는 강좌신청 릴레이션은 다음과 같은 삽입, 갱신, 삭제 이상 현상이 발생할 수 있다.
삽입 이상
P005 강사가 중급토익 강좌를 담당하게 되었지만, 이 강좌를 신청한 고객이 없다면, 이 내용을 강좌신청 릴레이션에 삽입할 수 없다.
갱신 이상
P004 강사가 담당하는 인터넷 강좌가 중급 토익으로 변경되면 P004 강사와 관련된 2개의 투플에서 인터넷강좌 속성의 값을 모두 중급 토익으로 동일하게 변경해야 한다. 만약 1개만 변경하면 P004 강사가 인터넷 강좌를 여러개 담당하게 되어 전제 조건에 모순되는 문제가 발생한다.
삭제 이상
고객 아이디가 banana인 고객이 인터넷강좌 신청을 취소해서 해당 고객에 대한 투플을 삭제하면, P002 강사가 기초토익 강좌를 담당하고 있다는 정보도 함께 삭제된다.