catsridingCATSRIDING|OCEANWAVES
Data

데이터베이스 정규화 이해하기

jynn@catsriding.com
Feb 23, 2024
Published byJynn
999
데이터베이스 정규화 이해하기

Database Normalization

데이터베이스 정규화는 중복 데이터를 제거하고 이상 현상(Anomalies)을 방지하는 아주 중요한 설계 기법입니다. 이상 현상은 데이터베이스에서 삽입, 갱신, 삭제 작업을 수행할 때 발생하는 예기치 않은 부작용을 의미합니다. 정규화를 통해 이러한 현상을 방지하고, 데이터 무결성을 유지할 수 있습니다.

더불어, 정규화된 데이터베이스는 애플리케이션 서비스 확장에 유연성을 제공합니다. 즉, 시스템의 증가하는 요구사항에 알맞게 데이터베이스 구조를 조정하고 확장하는 데 유리한 설계를 가능하게 합니다. 이로써, 데이터베이스 성능에 긍정적인 영향을 미치며 전반적인 시스템 성능 향상에 기여합니다.

이번 포스팅에서는 효율적이고 안정적인 데이터베이스 설계를 위해 데이터베이스 정규화에 대해 알아보겠습니다.

Prime and Non-Prime Attributes

데이터베이스에서, 키를 구성하는 속성을 주요 속성(Prime Attributes), 그리고 키를 구성하지 않는 속성을 일반 속성(Non-Prime Attributes) 이라고 합니다. 이 두 가지 속성 유형을 이해하는 것은 데이터베이스 정규화와 설계에 있어 중요한 기반이 됩니다. 이들 속성이 데이터 중복성을 줄이고, 데이터 무결성을 유지하며, 데이터 이상 현상을 제거하는 데 있어 중요한 역할을 하기 때문입니다.

Prime Attributes

주요 속성(Prime Attributes)은 연관관계 또는 테이블에 대해 고유성을 가진 속성입니다. 이들 속성은 후보 키(Candidate Key) 혹은 기본 키(Primary Key)로서 관계가 있는 튜플을 고유하게 구별하는 데 사용됩니다.

예를 들어, 학생 테이블에서 학생 번호는 학생들을 고유하게 구별할 수 있으므로 주요 속성으로 볼 수 있을 것입니다.

Non-Prime Attributes

반면에, 일반 속성(Non-Prime Attributes)은 키를 구성하는 부분이 아닙니다. 이러한 속성들은 레코드의 고유성에는 직접적인 관련이 없지만, 레코드에 대한 상세 정보를 제공하는 중요한 역할을 수행합니다.

다시 학생 테이블을 예로 들면, 학생의 이름, 주소, 학년과 같은 속성들은 각 학생을 고유하게 구별하지 못하므로 일반 속성으로 볼 수 있습니다.

STUDENTS
+------------------------+--------------------------------------+---------------------+
| Attribute(Column) Name | Description                          | Type of Attribute   |
+------------------------+--------------------------------------+---------------------+
| student_id             | Uniquely identifies each student     | Prime Attribute     |
| name                   | The name of the student              | Non-Prime Attribute |
| address                | The address of the student           | Non-Prime Attribute |
| grade                  | The grade of the student             | Non-Prime Attribute |
+------------------------+--------------------------------------+---------------------+

Anomalies in Databases

데이터베이스에서 이상 현상이란 데이터가 중복, 누락, 잘못 업데이트되거나 제거되는 등 부적절하게 처리되는 상황을 말합니다. 이러한 현상은 데이터의 무결성을 손상시키고, 응용 프로그램에서 예기치 않은 결과를 초래할 수 있습니다. 따라서, 데이터베이스 설계에서는 이러한 이상 현상을 최소화하는 것이 중요합니다.

데이터베이스에서 다음 세 가지 주요 이상 현상을 찾아볼 수 있습니다.

Insertion Anomaly

삽입 이상(Insertion Anomaly) 현상이란 데이터를 데이터베이스에 삽입하려고 할 때 발생하는 문제입니다. 삽입 이상현상의 대표적인 예는 특정 속성을 알아야만 행을 삽입할 수 있는 경우입니다.

예를 들어, 다음과 같이 작가와 그들이 쓴 책의 세부 정보를 기록하는 데이터베이스가 있다고 가정해봅니다:

WRITERS
+-----------+----------------+-----------------+
| writer_id | name           | book            |
+-----------+----------------+-----------------+
| 1         | Author 1       | Book 1          |
| 2         | Author 2       | Book 2          |
| 3         | Author 3       | Book 3          |
+-----------+----------------+-----------------+

아직 책을 출간하지 않은 신인 작가를 발견하여 이 작가의 정보를 데이터베이스에 입력하려고 할 때, 책에 대한 정보는 없으니 null로 처리해야 합니다. 이처럼 데이터를 입력하는 과정에서 불완전한 정보나 불필요한 정보가 삽입되는 경우를 삽입 이상현상이라고 합니다.

insert into WRITERS (writer_id, name, book)
values (4, 'New Writer', null);

삽입 이상현상은 데이터가 일관성을 잃거나 데이터 손실을 초래할 수 있으므로 데이터베이스 정규화를 사용하여 이러한 상황을 방지해야 합니다.

새로운 데이터는 쉽게 추가될 수 있어야 합니다. 적절한 데이터베이스 설계를 통해 기존의 데이터 무결성 규칙을 훼손하지 않고, 필요 이상의 데이터를 제공하지 않아도 새로운 데이터를 추가할 수 있어야 합니다.

Update Anomaly

갱신 이상(Update Anomaly) 현상이란 데이터베이스 내 데이터를 갱신(수정)할 때 발생하는 문제입니다. 이는 주로 중복된 데이터가 많을 때 발생하며, 일부만 갱신되어 데이터 간의 불일치가 생기는 경우를 말합니다.

예를 들어, 작가와 그들이 쓴 책의 세부 정보를 기록하는 아래와 같은 테이블이 있다고 가정해봅니다:

WRTIERS
+-----------+-----------------+-----------------+
| writer_id | name            | book            |
+-----------+-----------------+-----------------+
| 1         | Author 1        | Book 1          |
| 2         | Author 1        | Book 2          |
| 3         | Author 2        | Book 3          |
+-----------+-----------------+-----------------+

이 경우, 작가 이름 Author 1을 변경하려면 Author 1로 등록된 모든 레코드를 찾아 수정해야 합니다.

update WRITERS
set
    name = 'New Author 1'
where
    name = 'Author 1';

여기서 만약 실수나 뜻하지 않은 장애로 일부 레코드만 수정하게 된다면, 같은 작가에 대한 정보가 일관성을 갖지 못해 문제를 초래할 수 있습니다. 이를 갱신 이상현상이라고 합니다.

수정해야 하는 레코드의 수가 많거나, 다른 테이블과 복잡하게 연결되어 있는 경우, 이는 성능에도 부정적인 영향을 미칠 수 있습니다.

Deletion Anomaly

삭제 이상(Deletion Anomaly) 현상이란 데이터를 데이터베이스에서 삭제할 때 발생하는 문제를 말합니다. 이는 데이터가 서로 깊게 연결되어 있을 때 주로 발생하며, 특정 정보를 삭제하면 원하지 않게 관련 정보까지 삭제되는 상황을 가리킵니다.

예를 들어, 아래와 같이 작가와 그들이 쓴 책에 대한 정보를 저장한 테이블이 있습니다:

WRITERS
+-----------+-----------------+-----------------+
| writer_id | name            | book            |
+-----------+-----------------+-----------------+
| 1         | Author 1        | Book 1          |
| 2         | Author 2        | Book 2          |
| 3         | Author 3        | Book 3          |
+-----------+-----------------+-----------------+

만약 여기서 책 Book 1을 삭제하게 된다면, 연결된 작가 Author 1에 대한 정보까지 함께 삭제될 우려가 있습니다.

delete
from
    WRITERS
where
    book = 'Book 1';

이렇게 기대했던 것은 책 Book 1의 정보만을 제거하는 것이지만, 연계된 작가에 대한 정보까지 한꺼번에 삭제되는 경우를 삭제 이상현상이라고 합니다.

Previewing Normalization

본격적으로 데이터베이스 정규화를 시작하기 전에, WRITERS 테이블에서 발생한 각각의 이상 현상을 어떻게 해결할 수 있는지 검토해보겠습니다.

해결 방안으로 WRITERS 테이블을 두 개의 독립적인 테이블로 분리하는 것입니다. 먼저 작가의 정보만을 저장하는 새로운 테이블을 만듭니다. 이를 구분하기 쉽게 하기 위해 이 테이블을 AUTHORS라고 명명하겠습니다.

AUTHORS
+-----------+-----------------+
| author_id | name            |
+-----------+-----------------+
| 1         | Author 1        |
| 2         | Author 2        |
+-----------+-----------------+

그리고 책 정보를 담는 BOOKS 테이블을 추가합니다.

BOOKS
+---------+-----------------+-----------+
| book_id | title           | author_id |
+---------+-----------------+-----------+
| 1       | Book 1          | 1         |
| 2       | Book 2          | 1         |
| 3       | Book 3          | 2         |
+---------+-----------------+-----------+

테이블을 이렇게 분리함으로써 각 이상 현상은 다음과 같이 해결될 수 있습니다:

  • 삽입 이상현상: 책 데이터 없이도 작가 정보를 AUTHORS 테이블에 추가할 수 있습니다.
  • 갱신 이상현상: 만약 작가의 이름을 변경하고자 한다면, AUTHORS 테이블의 해당 레코드만 수정하여 전체 데이터의 일관성을 유지할 수 있습니다.
  • 삭제 이상현상: 책 정보가 BOOKS 테이블에서 삭제되더라도, 작가의 정보는 AUTHORS 테이블에서 안전하게 보존됩니다.

즉, 이와 같이 데이터베이스를 정규화함으로써 이상 현상을 예방하고 데이터의 일관성을 보장할 수 있습니다.

Understanding Database Normalization

데이터베이스 정규화(Database Normalization)의 핵심 기반은 함수적 종속성(Functional Dependency)이라는 개념입니다. 함수적 종속성은 관계형 데이터베이스 모델에서 중요한 역할을 하며, 한 속성 또는 속성 집합이 다른 속성 또는 속성 집합을 유일하게 식별하는 관계를 표현합니다.

예를 들어, 학번과 학생 이름에 관한 함수적 종속성이 있다고 가정했을때, 특정 학번을 가진 학생의 이름을 정확하게 알 수 있다면, 여기서 학번학생 이름을 함수적으로 결정하게 됩니다.

이런 함수적 종속성을 분석하고 활용함으로써, 데이터베이스의 정규화 과정을 통해 다음의 주요 목표를 이룰 수 있습니다:

  • 데이터 표현의 일관성: 정규화를 통해 데이터베이스에 동일한 정보가 복수로 저장되는 것을 방지할 수 있습니다. 기본적으로 정규화는 무결성을 보장하며, 이로 인해 데이터베이스 내의 모든 정보 간의 일관성 또한 보장하게 됩니다.
  • 최적의 구조 확보: 정규화에 의해 많은 수의 작은 테이블들이 만들어지는데, 이러한 방식은 데이터베이스의 구조를 좀 더 유연하게 만들어주며, 이는 데이터 관리를 용이하게 합니다.
  • 이상 현상 방지: 정규화로 인해 일관성을 유지하면서도 데이터 조작이 용이해집니다. 여러 테이블에서 중복 데이터를 관리하는 대신, 데이터를 한 곳에서만 관리하면 됩니다.

데이터베이스 정규화는 본질적으로 여섯 단계로 나누어집니다. 이론적으로는 이 여섯 단계를 모두 거쳐야 하지만, 실제로는 주로 세 번째 단계, 즉 제3정규형까지만 진행됩니다. 이는 제3정규형이 데이터의 중복을 최소화하고 무결성을 보장하므로, 실제 비즈니스 환경에서 발생하는 대부분의 요구사항을 만족시키기 때문입니다.

BCNF, 4NF, 5NF와 같은 고급 정규형은 특히 복잡한 데이터 모델이나 특수한 경우에 사용됩니다. 이러한 고급 정규형들은 데이터의 중복을 제거하고 무결성을 향상시키는 데 도움이 되지만, 설계 및 구현이 복잡해지고 종종 더 많은 테이블이 필요하기 때문에, 데이터베이스의 성능에 영향을 줄 수 있습니다.

  • 데이터베이스 정규화의 이점:
    • 데이터의 중복 최소화와 일관성 유지
    • 데이터 관리의 효율성 증가
    • 데이터베이스의 무결성 및 정확성 확보
  • 데이터베이스 정규화의 단점:
    • 과도한 정규화로 인한 처리 성능 저하
    • 테이블 분할에 따른 데이터베이스 복잡성 증가

이러한 점들을 고려할 때, 데이터베이스 정규화는 무결성과 효율성을 확립하는 데 중요한 과정이라는 사실을 알 수 있습니다. 이제 아래 STUDENT_COURSES 테이블을 정규화하는 과정을 살펴보며 정규화에 대해 더 깊이 이해해 보도록 하겠습니다:

MySQL
create table STUDENT_COURSES
(
    student_id      bigint,
    subject_code    varchar(50),
    grade           decimal(3, 2),
    subject_name    varchar(255),
    student_name    varchar(255),
    department_code varchar(50),
    department_name varchar(255)
);

insert into STUDENT_COURSES(student_id, subject_code, grade, subject_name, student_name, department_code, department_name)
values (2016053, 'CS101', 3.5, 'Programming', 'Kim Chulsoo', 'CS', 'Computer Science'),
       (2016053, 'CS102', 4.0, 'Algorithm', 'Kim Chulsoo', 'CS', 'Computer Science'),
       (2017033, 'ENG101', 3.0, 'English Conversation', 'Lee Younghee', 'ENG', 'English'),
       (2017033, 'ENG102', 3.5, 'English Grammar', 'Lee Younghee', 'ENG', 'English'),
       (2018023, 'BIO101', 3.7, 'Biology', 'Park Minsu', 'BIO', 'Biology'),
       (2018023, 'BIO102', 4.0, 'Genetics', 'Park Minsu', 'BIO', 'Biology'),
       (2019001, 'POL101', 3.2, 'Political Science', 'Kim Younggwang', 'POL', 'Political Science and Diplomacy'),
       (2019001, 'POL102', 3.4, 'International Politics', 'Kim Younggwang', 'POL', 'Political Science and Diplomacy'),
       (2019002, 'PSY101', 3.6, 'Introduction to Psychology', 'Lee Sungkyung', 'PSY', 'Psychology'),
       (2019002, 'PSY102', 4.0, 'Clinical Psychology', 'Lee Sungkyung', 'PSY', 'Psychology'),
       (2019003, 'SOC101', 3.0, 'Introduction to Sociology', 'Sungjoon', 'SOC', 'Sociology'),
       (2019003, 'SOC102', 3.3, 'Social Cultural Theory', 'Sungjoon', 'SOC', 'Sociology'),
       (2019004, 'BUS101', 3.7, 'Business Administration', 'Kim Yewon', 'BUS', 'Business'),
       (2019004, 'BUS102', 3.8, 'Marketing Theory', 'Kim Yewon', 'BUS', 'Business');

1NF: First Normal Form

제1정규형(1NF)은 데이터베이스의 정규화를 위한 첫번째 중요한 단계로, 이를 만족하기 위한 기본 규칙들은 다음과 같습니다:

  • 원자성(Atomicity): 테이블의 각 열(Column)은 더 이상 분해할 수 없는 원자값을 가져야 합니다. 즉, 하나의 필드가 여러 값, 리스트, 세트 또는 다른 복합 데이터 형식을 포함하면 안됩니다.
  • 유일성(Uniqueness): 테이블의 각 행(Row)은 서로 구별될 수 있어야 합니다. 즉, 모든 행에는 고유한 식별자(기본 키 또는 기본 키의 조합)가 있어야 합니다.
  • 순서 무관성(Order-Insensitivity): 행들 사이의 순서나, 열들 사이의 순서는 중요하지 않습니다. 행 및 열의 순서는 데이터의 논리적 구조에 영향을 미치지 않습니다.

제1정규형을 이용하면, 각 속성은 열 단위로 분할되고 각 열은 유일한 이름을 갖습니다. 또한 각 행은 데이터 레코드를 이루며 각각 유일한 식별자(Primary Key)를 통해 식별됩니다. 이렇게 되면 데이터의 중복성이 줄어들고, 데이터 조회, 수정, 삭제가 보다 효과적이게 됩니다.

제1정규형을 만족하는 데이터베이스 레코드의 형태는 아래와 같습니다:

STUDENT_COURSES
+----------+------------+-----+--------------------------+--------------+---------------+-------------------------------+
|student_id|subject_code|grade|subject_name              |student_name  |department_code|department_name                |
+----------+------------+-----+--------------------------+--------------+---------------+-------------------------------+
|2016053   |CS101       |3.50 |Programming               |Kim Chulsoo   |CS             |Computer Science               |
|2016053   |CS102       |4.00 |Algorithm                 |Kim Chulsoo   |CS             |Computer Science               |
|2017033   |ENG101      |3.00 |English Conversation      |Lee Younghee  |ENG            |English                        |
|2017033   |ENG102      |3.50 |English Grammar           |Lee Younghee  |ENG            |English                        |
|2018023   |BIO101      |3.70 |Biology                   |Park Minsu    |BIO            |Biology                        |
|2018023   |BIO102      |4.00 |Genetics                  |Park Minsu    |BIO            |Biology                        |
|2019001   |POL101      |3.20 |Political Science         |Kim Younggwang|POL            |Political Science and Diplomacy|
|2019001   |POL102      |3.40 |International Politics    |Kim Younggwang|POL            |Political Science and Diplomacy|
|2019002   |PSY101      |3.60 |Introduction to Psychology|Lee Sungkyung |PSY            |Psychology                     |
|2019002   |PSY102      |4.00 |Clinical Psychology       |Lee Sungkyung |PSY            |Psychology                     |
|2019003   |SOC101      |3.00 |Introduction to Sociology |Sungjoon      |SOC            |Sociology                      |
|2019003   |SOC102      |3.30 |Social Cultural Theory    |Sungjoon      |SOC            |Sociology                      |
|2019004   |BUS101      |3.70 |Business Administration   |Kim Yewon     |BUS            |Business                       |
|2019004   |BUS102      |3.80 |Marketing Theory          |Kim Yewon     |BUS            |Business                       |
+----------+------------+-----+--------------------------+--------------+---------------+-------------------------------+

2NF: Second Normal Form

제2정규형(2NF)의 목적은 부분적 종속성(Partial Dependency)을 제거하는 것입니다. 부분적 종속성이란 속성들이 복합키의 일부분에만 의존적인 경우를 말합니다. 따라서, 제2정규형을 이루기 위해선 다음의 조건들이 충족되어야 합니다:

  • 테이블이 제1정규형을 만족해야 합니다.
  • 테이블의 키가 아닌 모든 일반 속성들이(Non-Prime Attributes) 후보 키(Candidate Keys) 전체에 종속적이어야 합니다.

제1정규형을 충족하는 테이블을 제2정규형으로 전환하는 과정은 명확한 원칙에 따라 이루어집니다:

  • 각 후보 키를 기준으로, 해당 키에 완전히 함수적으로 종속된 더 이상 분해되지 않는 속성들을 분류하여, 이들의 함수적 종속성이 완전하게 표현될 수 있도록 새로운 테이블들을 생성합니다.
  • 원래의 테이블에서는 이러한 분해된 일반 속성들을 제거하고, 오직 후보 키들만을 유지합니다.

현재의 STUDENT_COURSES 테이블은 student_idsubject_code를 포함하고 있어, 이 두 속성을 가지고 학생들이 수강하는 과목을 특정할 수 있습니다. 이들은 학생과 과목을 고유하게 식별하는 후보 키로 간주할 수 있습니다.

STUDENT_COURSES
+---------------+------------+---+
|Field          |Type        |Key|
+---------------+------------+---+
|student_id     |bigint      |   |
|subject_code   |varchar(50) |   |
|grade          |decimal(3,2)|   |
|subject_name   |varchar(255)|   |
|student_name   |varchar(255)|   |
|department_code|varchar(50) |   |
|department_name|varchar(255)|   |
+---------------+------------+---+

학생 관련 정보는 모두 student_id에 종속되어 있어, 각 학생별로 독립적으로 관리됩니다. 이런 패턴을 통해 볼 때, 학생 관련 정보를 STUDENTS라는 별도의 테이블로 분리하여 관리하는 것이 효율적임을 알 수 있습니다.

-- 1. `STUDENTS` 테이블 생성:
create table STUDENTS
(
    student_id      bigint primary key auto_increment,
    student_name    varchar(255),
    department_code varchar(50),
    department_name varchar(255)
);

-- 2. `STUDENT_COURSES` 학생 데이터 `STUDENTS`로 이관:
insert into STUDENTS (student_id, student_name, department_code, department_name)
select distinct
    student_id,
    student_name,
    department_code,
    department_name
from
    STUDENT_COURSES;

-- 3. `STUDENT_COURSES` 학생 일반 속성 제거:
alter table STUDENT_COURSES
    drop column student_name,
    drop column department_code,
    drop column department_name;
  1. 학생 정보를 관리하는 STUDENTS 테이블을 생성합니다.
  2. STUDENT_COURSES 테이블의 학생 데이터를 STUDENTS 테이블로 이관합니다.
  3. STUDENT_COURSES 테이블에서 student_id를 제외한 학생의 일반 속성을 모두 제거합니다.

마찬가지로, 과목 정보는 subject_code에 종속되어 있어, 이 역시 COURSES라는 별도의 테이블로 분리가 가능합니다:

-- 1. `COURSES` 테이블 생성:
create table COURSES
(
    subject_code varchar(50) primary key,
    subject_name varchar(255)
);

-- 2. `STUDENT_COURSES` 과목 데이터 이관:
insert into COURSES (subject_code, subject_name)
select
    subject_code,
    subject_name
from
    STUDENT_COURSES;

-- 2. `STUDENT_COURSES` 과목 일반 속성 제거:
alter table STUDENT_COURSES
    drop column subject_name;
  1. 과목 정보를 관리하는 COURSES 테이블을 생성합니다.
  2. STUDENT_COURSES 테이블의 과목 데이터를 COURSES 테이블로 이관합니다.
  3. STUDENT_COURSES 테이블에서 subject_code를 제외한 과목의 일반 속성을 모두 제거합니다.

이처럼 데이터를 적절한 테이블로 분리한 후, 기존의 STUDENT_COURSES 테이블을 연관관계 테이블로서 활용하여 학생과 과목의 관계를 명확하게 나타낼 수 있습니다:

alter table STUDENT_COURSES
    add id bigint primary key auto_increment first,                   -- PK 추가
    add foreign key (student_id) references STUDENTS(student_id),     -- 학생 테이블 FK 설정
    add foreign key (subject_code) references COURSES(subject_code);  -- 과목 테이블 FK 설정

결과적으로 STUDENT_COURSES, STUDENTS, COURSES 이렇게 세 개의 테이블 모두 제2정규형를 만족하는 구조를 갖게 됩니다.

# STUDENT_COURSES
+--+----------+------------+-----+
|id|student_id|subject_code|grade|
+--+----------+------------+-----+
|1 |2016053   |CS101       |3.50 |
|2 |2016053   |CS102       |4.00 |
|3 |2017033   |ENG101      |3.00 |
|4 |2017033   |ENG102      |3.50 |
|5 |2018023   |BIO101      |3.70 |
|6 |2018023   |BIO102      |4.00 |
|7 |2019001   |POL101      |3.20 |
|8 |2019001   |POL102      |3.40 |
|9 |2019002   |PSY101      |3.60 |
|10|2019002   |PSY102      |4.00 |
|11|2019003   |SOC101      |3.00 |
|12|2019003   |SOC102      |3.30 |
|13|2019004   |BUS101      |3.70 |
|14|2019004   |BUS102      |3.80 |
+--+----------+------------+-----+

# STUDENTS
+----------+--------------+---------------+-------------------------------+
|student_id|student_name  |department_code|department_name                |
+----------+--------------+---------------+-------------------------------+
|2016053   |Kim Chulsoo   |CS             |Computer Science               |
|2017033   |Lee Younghee  |ENG            |English                        |
|2018023   |Park Minsu    |BIO            |Biology                        |
|2019001   |Kim Younggwang|POL            |Political Science and Diplomacy|
|2019002   |Lee Sungkyung |PSY            |Psychology                     |
|2019003   |Sungjoon      |SOC            |Sociology                      |
|2019004   |Kim Yewon     |BUS            |Business                       |
+----------+--------------+---------------+-------------------------------+

# COURSES
+------------+--------------------------+
|subject_code|subject_name              |
+------------+--------------------------+
|BIO101      |Biology                   |
|BIO102      |Genetics                  |
|BUS101      |Business Administration   |
|BUS102      |Marketing Theory          |
|CS101       |Programming               |
|CS102       |Algorithm                 |
|ENG101      |English Conversation      |
|ENG102      |English Grammar           |
|POL101      |Political Science         |
|POL102      |International Politics    |
|PSY101      |Introduction to Psychology|
|PSY102      |Clinical Psychology       |
|SOC101      |Introduction to Sociology |
|SOC102      |Social Cultural Theory    |
+------------+--------------------------+

database-normalization_00.png

3NF: Third Normal Form

제3정규형(3NF)의 주 목적은 간접적인 의존성, 즉 이행적 종속성을 제거하는 것입니다. 이행적 종속성이란 속성간의 간접적인 관계를 의미합니다. 예를 들어, A, B, C 세 가지 속성이 있을 때, A의 값이 B를 정하고, B의 값이 C를 정하는 관계를 이행적 종속성이라고 합니다.

이 형태는 식별자 역할을 하는 것이 아닌 속성이 실질적으로 다른 속성을 식별하는 경우를 포함하게 됩니다. 그러므로, 제3정규형을 만들기 위해서는 다음과 같은 조건들이 충족되어야 합니다:

  • 테이블이 제2정규형을 만족해야 합니다.
  • 테이블에 이행적 종속성이 없어야 합니다. 즉, 일반 속성들이(Non-Prime Attributes) 식별 키(Primary Key)에만 의존해야 합니다.

현재 STUDENTS 테이블에서 학과명은 학과 코드에 대한 종속적인 속성으로도 볼 수 있습니다.

STUDENTS
+---------------+------------+---+
|Field          |Type        |Key|
+---------------+------------+---+
|student_id     |int         |PRI|
|student_name   |varchar(255)|   |
|department_code|varchar(50) |   |
|department_name|varchar(255)|   |
+---------------+------------+---+

이를 통해 학과에 대한 정보는 별도의 테이블 DEPARTMENTS로 분리할 수 있습니다:

-- 1. `DEPARTMENTS` 테이블 생성:
create table DEPARTMENTS
(
    department_code varchar(50) primary key,
    department_name varchar(255)
);

-- 2. `STUDENTS` 학과 데이터 `DEPARTMENTS`로 이관:
insert into DEPARTMENTS (department_code, department_name)
select
    department_code,
    department_name
from
    STUDENTS;

-- 3. `STUDENTS` 학과 일반 속성 제거:
alter table STUDENTS
    drop column department_name;

-- 4. `STUDENTS` 학과 코드 FK 설정:
alter table STUDENTS
    add foreign key (department_code) references DEPARTMENTS(department_code),
  1. 학과 정보를 관리하는 DEPARTMENTS 테이블을 생성합니다.
  2. STUDENTS 테이블의 학과 데이터를 DEPARTMENTS 테이블로 이관합니다.
  3. STUDENTS 테이블에서 학과 정보와 관련된 일반 속성들을 제거합니다.
  4. STUDENTS 테이블의 department_code를 외래키로 설정합니다.

결과적으로 STUDENTS 테이블의 이행적 종속관계가 제거되고 학과 정보가 DEPARTMENTS 테이블로 분리되면서 제3정규형을 만족하게 됩니다:

database-normalization_01.png

지금까지의 과정을 진행하면서, 데이터베이스 정규화는 객체 지향 프로그래밍의 단일 책임 원칙(Single Responsibility Principle)과 상당한 유사성을 가지고 있다는 생각이 들었습니다. 특히, 각 테이블이 고유한 역할을 가지며 그에 부합하는 데이터만을 유지하고 관리하는 측면에서 이 같은 유사성이 드러나는 것 같습니다.

데이터베이스 설계는 주요 속성과 일반 속성의 선정부터, 응용 프로그램의 요구 사항, 성능, 보안, 미래 확장성 등 다양한 요소가 함께 고려되어야 합니다. 이렇게 복잡한 요소들을 적절히 고려하고 판단하기 위해서는 깊이 있는 지식과 경험이 필요합니다. 이를 위해 끊임없이 배우고, 연습해야겠습니다. 🏛


  • Database
  • MySQL