IT's Jenna

3. 정규화 논리(첫 번째) - 함수 종속성 본문

Study/관계형 데이터 베이스 실전 입문

3. 정규화 논리(첫 번째) - 함수 종속성

developer Jenna 2021. 5. 21. 16:47
정규화란?
정규화가 왜 필요한가?
정규형

 

지금까지 관계형 모델에 대해 알아보았다. 그렇다면 이제 우리가 공부한 관계형 모델을 구성하기 위해서 실제 DB를 어떻게 설계할지 생각해보자!

 

데이터와 쿼리의 복잡성은 비례한다. 즉 데이터의 표현이 복잡해지면 쿼리 또한 깔끔하게 작성할 수 없다. 따라서 DB를 어떻게 설계하느냐에 따라 전체 프로그램의 로직이 달라지는 것이다. 그렇다면 DB를 대체 어떻게 설계해야 할지 우려가 될 것이다. 이때 만능 치트키처럼 사용할 수 있는 DB 설계 이론이 있다. 그것이 바로 정규화 이론이다!

1. 정규화란?

정규화란, 관계형 모델을 전제로 구축된 데이터 베이스 설계 이론이다.

 

조금 더 쉽게 접근하기 위해 정규화의 국어사전적 의미를 살펴보자. 정규화란 어떤 대상을 일정한 규칙이나 기준에 따르는 정규적인 상태로 바꾸거나, 비정상적인 대상을 정상적으로 되돌리는 과정을 뜻한다.

이를 바탕으로 데이터 베이스 설계에서의 정규화란 정규화 이론이 가지고 있는 특정한 규칙을 바탕으로 관계형 모델을 구성하는 것이라 할 수 있다.

2. 정규화가 왜 필요한가?

그렇다면 정규화 이론을 왜 사용해야 할까? 이는 데이터에 모순, 다시 말해 논리적으로 잘못된 데이터가 생기는 것을 방지하기 위함이다. 예시 릴레이션을 보자.

<릴레이션의 변칙>

위 릴레이션을 보면 정은이가 2학년과 3학년에 동시에 속해있다. 따라서 해당 릴레이션을 통해 정은이가 2학년인지 3학년인지 답을 할 수 없다. 이렇듯 DB 설계가 잘못되면 릴레이션의 질의에 대해서 명확하게 대답할 수 없는 모순이 생기고 이렇게 모순이 생긴 상태변칙이라고 한다.

 

변칙이 발생하는 근본적인 원인은 데이터의 중복에 있다. 위의 예시에서도 같은 학생의 학년이 여러 번 반복되면서 모순이 발생하였다. 따라서 데이터의 중복을 최대한 피하면서 DB를 설계해야 하고, 이렇게 데이터의 중복을 제거하는 데에 도움이 되는 것이 바로 정규화 이론이다.

3. 정규형

정규화에는 총 7단계가 있고, 숫자가 높을수록 좋은 상태 즉, 중복이 적은 상태이다. 각 단계를 정규형(Normal Form, NF)라고 한다.

  • 제1 정규형(1NF)
  • 제2 정규형(2NF)
  • 제3 정규형(3NF)
  • 보이스코드 정규형(BCNF)
  • 제4 정규형(4NF)
  • 제5 정규형(5NF)
  • 제6 정규형(6NF)

7단계의 정규형 중에서 현재 실질적으로 사용되는 정규형은 BCNF와 5NF이다. 따라서 다른 정규형들은 실제로 DB를 설계할 때 신경 쓰지 않아도 되지만 공부를 위해 모두 살펴보도록 하겠다.


< 제1 정규형(1NF) >

  • 정규화의 출발점
  • 제1 정규형의 조건 : 데이터가 릴레이션이어야 한다.

이는 관계형 모델에서는 이미 충족되는 조건이기 때문에 해당 조건은 SQL에 적용된다. 즉, SQL의 테이블이 릴레이션이어야 한다는 것이 1NF의 핵심이다. SQL 테이블의 조건은 다음과 같다.

  1. 행이 위에서 아래로 정렬돼 있지 않다.
  2. 열이 왼쪽에서 오른쪽으로 정렬돼 있지 않다.
  3. 중복하는 행이 존재하지 않는다.
  4. 각 행과 열의 교차점(열의 값)은 도메인(데이터형)에 속하는 요소의 값을 딱 한 개만 가진다.
  5. 모든 열의 값은 정의된 것이어야 하고 각 행은 항상 존재한다.
  • 1 & 2 : 실제로 SQL에서는 행과 열에 순서가 존재한다. 하지만 여기서 말하는 "정렬돼 있지 않다"의 포인트는 테이블에 순서에 상관없이 연산되어야 한다는 것이다. 따라서 쿼리문을 작성할 때 행과 열의 위치에 의존하지 않도록 해야 한다.
  • 3 : 행의 중복을 피하기 위해 기본키나 유니크키처럼 제약을 붙일 수 있다. 이를 통해 행 자체가 중복되는 것은 피할 수 있으나 위의 예시처럼 결과값이 중복되어 나올 수 있다는 점에 유의해야 한다.
  • 4 : 이론적으로 요소의 값은 값이 원자성을 가져야 한다. 즉 더 이상 분해할 수 없는 최소 단위여야 한다. 하지만 이것은 요소를 어떻게 나누느냐에 따라 변할 수 있다. 따라서 값은 도메인 중에서 골라낸 하나의 요소라고 정의한다. (데이터의 최소 단위 즉, 도메인의 요소를 어떻게 설계하느냐가 DB설계의 첫걸음이 되는 이유이다!)
  • 5 : NULL값이 포함되면 해당 값을 알 수 없기 때문에 릴레이션 연산이 불가하다. 따라서 테이블에는 NULL을 포함하지 않는 것이 원칙이나 실무적으로 힘든 경우들이 발생한다. NULL에 대해선 7장에서 자세히 설명한다.

계속해서 정규형을 알아가는데에 있어 꼭 필요한 개념 몇 가지만 정리하고 넘어가도록 하겠다.

슈퍼키(Super Key)

슈퍼키란, 테이블에서 각 행을 유일하게 식별할 수 있는 하나 또는 그 이상의 속성들의 집합을 의미한다. 슈퍼키는 유일성을 만족해야 한다. 즉, 해당 키 하나로 특정 행을 바로 찾아낼 수 있는 고유한 데이터 속성이다.

  • 학번, 주민번호 속성은 그 자체로 슈퍼키가 될 수 있다.
  • 이름과 나이를 합쳐서 하나의 속성으로 만들면 슈퍼키로 사용할 수 있다.

후보키(Candidate Key)

후보키란, 테이블에서 각 행을 유일하게 식별할 수 있는 최소한의 속성들의 집합을 의미한다. 후보키는 유일성최소성을 동시에 만족해야 한다.

  • 학번과 주민번호는 후보키가 될 수 있다.
  • 이름과 나이의 조합은 최소성을 만족하지 않기 때문에 후보키가 될 수 없다.

기본키(Primary Key)

기본키란, 후보키들 중에서 선택한 하나의 키를 의미한다. 기본키 개념은 관계형 모델에는 없고 SQL 테이블에서만 사용된다. 릴레이션에서 여러 후보키들은 의미적으로나 기능적으로 차이가 없다.


함수 종속성

2NF - BCNF를 이해함에있어 포인트가 되는 부분이 바로 함수 종속성이다. 앞서 말한 것처럼 정규형은 단계가 높을수록 좋고 BCNF는 함수 종속성이 최대한 배제된 최적의 상태이다. 따라서 2NF, 3NF 단계에선 함수 종속성을 더욱 배제하여 BCNF단계로 나아가게끔 정규화를 해야 한다.

 

그렇다면 함수 종속성이란 뭘까? 함수 종속성의 정의는 다음과 같다.

  • 어떤 릴레이션 R에서 X와 Y를 각각 R 속성의 부분집합이라 했을 때, 속성 X의 값 각각에 대해 항상 속성 Y의 값이 오직 하나만 연결될 때 Y는 X에 함수 종속한다고 하고 이러한 관계를 X -> Y라고 기술한다.
  • X의 값을 알면 Y의 값을 알 수 있다.
  • X를 결정자, Y를 종속자라고 한다.

아래 실제 예시를 보자.

<함수 종속성 예시1>

  • 학번에 의해 이름과 학과는 구분된다. 즉 이름과 학과는 학번에 함수 종속한다고 할 수 있고 다음과 같이 나타낼 수 있다.
  • {학번} -> {이름, 학과}

<함수 종속성 예시2>

  • 이름은 학번에 의해 구분될 수 있다. 하지만 점수는 학번과 과목코드에의해 결정된다.
  • 이때 이름은 학번과 과목코드에 의해서도 결정될 수 있다.
  • {학번} -> {이름}
  • {학번, 과목코드} -> {점수}
  • {학번, 과목코드} -> {이름}

이제 필요한 개념들을 알았으니 다음 정규형들을 알아보자.

< 제2 정규형(2NF) >

바로 위의 예제에서 이름 속성은 학번 속성에도 종속하고, 과목코드 속성에도 종속하는데 이렇게 여러 속성에 종속되는 것을 부분 함수 종속성이라고 한다.

  • 제2 정규형의 조건 : 부분 함수 종속성을 갖지 않는다.

부분 함수 종속성을 갖지 않는 것이 왜 중요할까? 위에서 언급한 것처럼 데이터에 모순이 생기는 원인은 중복에서 온다고 했다. 아래 두 가지 예시를 보자.

  • 예시1, 예시2  릴레이션은 학년은 이름과 수업에 함수 종속한다 : {이름, 수업} -> {학년}
  • 예시1에서 {이름} -> {학년} 함수 종속을 보면 값이 중복되어 정은이의 학년을 명확하게 알 수 없는 모순이 존재한다.
  • 예시2에서 {이름} -> {학년} 함수 종속은 모순이 존재하지 않아도 데이터 자체가 중복된다. 이렇게 중복되는 경우 데이터 일부를 수정하게 되면 예시1과 같은 모순이 발생할 수 있다.

해결방법

부분 함수 종속성을 해결하기 위해서는 하나의 릴레이션을 여러 개의 릴레이션으로 분해해야 한다. 이때 특정 속성만 가져오는 프로젝션 연산을 활용하고, 여러 릴레이션으로 분해할 때 기존 릴레이션의 정보를 잃어버려서는 안 된다. 이것을 무손실 분해라고 한다.

 

위의 예시2를 무손실 분해하면 다음과 같다.

  • 각 릴레이션은 {이름}->{수업}, {이름}->{학년}으로 함수 종속한다.
  • 두 릴레이션을 JOIN으로 결합할 경우 온전한 데이터를 받아올 수 있다.

<제3 정규형(3NF)>

  • 제3 정규형의 조건 : 추이 함수 종속성을 갖지 않는다.

추이 함수 종속성이란 키가 아닌 속성 사이의 함수 종속성을 의미한다. 예시를  살펴보자.

  • {수업} -> {과목코드} 함수 종속성이 성립한다.
  • {이름} -> {수업}, {수업}->{과목코드}의 함수 종속성이 성립하면 {이름}->{과목코드}의 함수 종속성이 성립하게 된다. 이렇게 되면 해당 데이터가 논리적으로 맞지 않다.

해결방법

제2 정규형과 똑같이 릴레이션을 무손실 분해하여 상위 정규형으로 정규화한다.


<보이스코드 정규형(BCNF)>

  • 보이스코드 정규형의 조건 : 키만 함수 종속해야 한다.

중복 함수 종속성과 추이 함수 종속성을 모두 배제하지만 BCNF에는 부합하지 않는 경우가 있다. 바로 후보키가 키가 아닌 속성에 함수 종속하는 경우이다. 다음 예시를 보자.

<BCNF가 아닌 릴레이션>

  • {이름, 학과} -> {연구실} 함수 종속한다. 해당 경우는 부분 함수 종속은 아니다.
  • 연구실이 학과보다 자세한 정보이고 {연구실}->{학과} 함수 종속한다.
  • {이름,학과}, {이름,연구실} 모두 후보키가 될 수 있다.
  • {이름, 연구실}을 후보키로 사용하는 경우 부분 종속성이 발생하여 2NF를 만족하지 않는다.

해결방법

BCNF의 경우 명확하지 않은 후보키가 없어야한다. 3NF를 만족하더라도 후보키가 될 수 있는 다른 경우가 있는지 살펴보고 무손실 분해를 해야 한다. 즉 결과적으로 BCNF는 오직 키만 함수 종속하는 릴레이션이 된다.

<무손실 분해 예시3>


지금까지 정규화가 무엇이고, 정규화가 왜 필요한지, 그리고 정규형의 종류 1NF - BCNF까지 알아보았다. 다음장에서는 정규형 4NF - 6NF까지 설명하도록 하겠다.

 

<참고>

https://jerryjerryjerry.tistory.com/49

https://yaboong.github.io/database/2018/03/09/database-anomaly-and-functional-dependency/

Comments