10분 기술세미나

주제: 데이터베이스 정규화

안녕하세요. 커널360 백엔드 1기 4셀 신종민입니다.

제가 이번에 준비한 발표 주제는 데이터베이스의 정규화에 관한 내용입니다.
부트업과 해커톤, 그리고 End to End 프로젝트를 거치면서 데이터베이스에 대해서 모르는 점이 많다는 점을 깨달았습니다.
파이널 프로젝트 외에도 앞으로도 백엔드 개발자로서 반드시 알아야 한다는 점을 깨닫고 데이터베이스에 대해 잘 알고싶어 발표 주제를 정하게 되었습니다.


1. 정규화의 정의

정규화란 무엇일까요? 위키피디아에서는 다음과 같이 나왔습니다.

관게형 데이터베이스의 설계에서 중복을 최소화하게 데이터를 구조화하는 프로세스

크고, 제대로 조직되지 않은 테이블들과 관계들을 작고 잘 조직된 테이블과 관계들로 나누는 것

Database normalization is a database schema design technique, by which an existing schema is modified to minimize redundancy and dependency of data.(데이터베이스 정규화를 통해 데이터의 중복과 의존성을 최소화할 수 있다.)

이라고 합니다.

정규화는 데이터베이스 설계에서 중요한 개념 중 하나로, 중복을 최소화하고 데이터를 구조화하는 프로세스입니다. 이를 통해 데이터베이스의 효율성을 높이고 무결성을 유지할 수 있습니다.


2. 정규화의 목적

데이터베이스 정규화의 구체적인 목적은 다음과 같습니다.

  • 데이터베이스의 변경 시 이상현상 제거
  • 데이터베이스 구조 확장 시 재 디자인 최소화
  • 사용자에게 데이터 모델을 더욱 의미있게 만듦
  • 다양한 질의 지원
  • 주된 목적은 중복을 최소화하고 데이터의 무결성을 유지하는 것.

여기서 주요한 개념을 짚고 넘어가야 할 것 같습니다. 첫 번째로 이상현상입니다.

이상현상이란?

테이블의 수정시 발생하는 원치 않는 부작용을 이상현상이라고 한다. 이상현상에는 갱신이상, 삽입 이상, 삭제 이상이 있다.

  1. 삽입이상: 자료를 삽입할 때 의도하지 않은 자료까지 삽입해야만 테이블에 추가가 가능한 현상을 말한다.
  2. 갱신이상: 중복된 데이터 중 일부만 수정되어 데이터 모순이 일어나는 현상
  3. 삭제이상: 어떤 정보를 삭제하면, 의도하지 않은 다른 정보까지 삭제되어버리는 현상

3. 정규화의 단계

정규화의 단계는 제1정규화, 제2정규화, 제3정규화, BCNF정규화, 제4정규화, 제5정규화로 총 6단계가 있으며 실무에서는 보통 제3정규화나 BCNF 정규까지 진행한다고 합니다.

정규화는 단계적으로 이루어지며 각 단계는 특정한 종속성을 해결하고 데이터의 일관성을 향상시킵니다.

제1정규화

제1정규화란 테이블의 컬럼이 원자값을 갖도록 하는 것입니다. 우리가 일 대 다 연관관계를 설정할 때, 객체는 일 쪽이 다 쪽의 객체를 포함하는 반면에, 관계 테이블은 다 대 일 관계에서 일의 키를 ‘다’쪽이 foreign 키로 가지고 있는 것과 관련이되어 있습니다.

제1정규화를 달성하지 않으면 어떤 문제가 있을까요? 즉 하나의 컬럼이 원자화되지 않거나, 동일한 값을 가지는 컬럼이 여러 가지가 나타나게 된다면 어떤 문제가 생길까요?

제1정규화를 지키지 않으면 데이터베이스에서 어떤 문제가 발생할 수 있는지를 예시를 통해 자세하게 설명하겠습니다.

제1정규화의 주요 목표는 각 컬럼이 원자적인 값을 가져야 한다는 것입니다. 즉, 각 컬럼의 값은 더 이상 분해되거나 중첩되지 않아야 합니다. 제1정규화를 위반하면 다음과 같은 문제가 발생할 수 있습니다.

예시

고객 정보를 저장하는 테이블이 있다고 가정해봅시다.

고객ID 이름 전화번호
1 홍길동 010-1234-5678
2 김영희 02-9876-5432
3 이철수 010-1111-2222

이 테이블은 초기에는 제1정규화를 따르고 있습니다. 그러나 만약 전화번호 컬럼에 여러 전화번호를 저장하려고 한다면, 제1정규화를 위반하게 됩니다.

고객ID 이름 전화번호
1 홍길동 010-1234-5678
2 김영희 02-9876-5432
3 이철수 010-1111-2222, 02-3333-4444

위의 예시에서는 고객ID 3의 레코드에서 전화번호가 두 개 이상이면서 컬럼에 여러 전화번호가 중첩되어 저장되어 있습니다. 이는 제1정규화를 위반한 상태입니다.

문제점

  1. 데이터 중복성: 전화번호 정보가 중첩되어 저장되면서 데이터 중복이 발생합니다. 이로 인해 데이터 일관성이 깨질 수 있습니다.

  2. 검색 및 정렬 어려움: 특정 전화번호를 검색하거나 정렬하는 것이 어려워집니다. 또한 이러한 중첩된 데이터를 처리하는 쿼리 작성이 복잡해집니다.

  3. 확장성 문제: 새로운 전화번호를 추가하거나 기존 전화번호를 수정할 때 일관성을 유지하기 어려워집니다.

이처럼 제1정규화를 위반하면 데이터의 일관성과 유지보수가 어려워지는 문제가 발생할 수 있습니다. 따라서 각 컬럼은 원자적인 값을 가져야 하며, 필요한 경우 별도의 테이블을 생성하여 관계를 맺어주는 것이 좋습니다.


제2정규화

제2정규화를 쉽게 설명하자면, 현재 테이블의 주제와 관련이 없는 컬럼을 별도의 테이블로 분리하는 작업을 말합니다. 제2정규화는 기본 키가 복합키로 되어있는 경우, 한 필드가 기본키를 이루는 일부 필드에 종속되는 현상이 있을 때 부분 종속성이 있다고 하는데, 이 부분 종속성을 제거하는 과정을 제2정규화라고 합니다.

따라서 부분 함수 종속성은 기본키가 복합키로 되어 있을 경우 발생합니다.

완전 함수 종속성: 모든 속성이 기본 키에 종속됐을 경우 완전 함수 종속성이 있다고 합니다.

제2정규화를 이해하기 위해, 우선 제2정규화가 지켜지지 않은 상황에서 발생할 수 있는 문제를 예시를 통해 살펴보겠습니다.

예시

고객과 주문 정보를 저장하는 테이블이 있다고 가정해봅시다.

고객 테이블 (Customer Table):

고객ID 이름 주소
1 홍길동 서울 강남구
2 김영희 부산 해운대구
3 이철수 인천 남동구

주문 테이블 (Order Table):

고객ID 주문일자 상품 가격
1 2022-01-01 노트북 1,500,000
2 2022-01-02 스마트폰 800,000
1 2022-01-03 테블릿 600,000
3 2022-01-04 노트북 1,000,000

여기서 주문 테이블은 고객 테이블과 관련이 있습니다. 그러나 주문 테이블에서는 각 주문의 상품과 가격 정보가 함께 저장되어 있습니다.

문제점

  1. 부분 종속성: 위의 주문 테이블은 (고객ID, 주문일자, 상품)이 복합키를 이루는데요, 상품의 가격은 기본키가 아닌 일부 컬럼인 상품에만 종속되어 있습니다.

  2. 데이터 중복성: 같은 상품을 여러 번 주문 했을 경우 같은 상품에 대한 가격이 곳곳에 흩어져 중복되어 저장되어 있습니다.

제2정규화의 적용

제2정규화는 부분 종속성을 해결하기 위한 것입니다. 주문 테이블을 정규화하여 두 개의 테이블로 나누어 보겠습니다.

고객 테이블 (Customer Table):

고객ID 이름 주소
1 홍길동 서울 강남구
2 김영희 부산 해운대구
3 이철수 인천 남동구

주문 테이블 (Order Table):

고객ID 주문일자(년-월-일)) 상품 ID
1 2022-01-01 1001
2 2022-01-02 1002
1 2022-01-03 1003
3 2022-01-04 1001

상품 테이블 (Product Table):

상품ID 상품 가격(원)
1001 노트북 1,500,000
1002 스마트폰 800,000
1003 테블릿 600,000
1004 데스크탑 2,000,000

이렇게 분리된 테이블은 각 테이블이 각자의 의미를 가지며, 부분 종속성 문제가 해결됩니다. 고객 테이블은 주문 테이블에 대해 부분 종속성이 없어지고, 데이터 중복성이 줄어들어 더 효율적인 데이터 관리가 가능해집니다.


제3정규화

제3정규화는 이행함수 종속성을 제거하는 과정을 말합니다. 이행하수 종속성이란 어느 컬럼이 기본 키가 아닌 다른 컬럼에 정속되는 현상을 말합니다.

자세한 예시를 통해 이행함수 종속성을 이해해보겠습니다.

고려할 테이블은 학생과 학과에 대한 정보를 담고 있는 테이블입니다.

학생 테이블 (Students Table):

학번 이름 전공
1001 홍길동 컴퓨터과학
1002 김영희 경영학
1003 이철수 전자공학

여기서 학번은 이름을 결정하고, 이름은 전공을 결정합니다. 이 경우, 학번 → 이름, 이름 → 전공이 성립합니다.

이제 이를 정규화하기 위해 학번과 이름을 가지는 테이블과 이름과 전공을 가지는 테이블로 나누어 보겠습니다.

학생 테이블 (Students Table):

학번 이름
1001 홍길동
1002 김영희
1003 이철수

전공 테이블 (Major Table):

이름 전공
홍길동 컴퓨터과학
김영희 경영학
이철수 전자공학

이제 학번과 이름이 하나의 테이블에서 다른 테이블로 분리되었습니다. 이를 통해 학번이 이름에, 이름이 전공에 이행함수 종속되던 문제를 해결할 수 있습니다. 이렇게 데이터 중복성을 최소화하고 테이블 간의 의미 있는 관계를 유지하며 정규화가 이뤄진 것입니다.


마무리

적절한 수준의 데이터베이스 정규화로 데이터를 중복되지 않고 이상현상이 발생하지 않도록 할 수 있습니다. 하지만 정규화를 하면 join 연산의 필요성도 늘어나서 비정규화 과정을 거치는 사례도 있는만큼 상황에 맞는 적절한 전략이 필요합니다.