데이터베이스 설계에서 **제2형 정규화(2NF, Second Normal Form)**는 제1형 정규화(1NF)를 만족하면서, 부분 함수 종속을 제거하는 것을 목표로 한다. 여기서 부분 함수 종속이란, 테이블의 기본 키가 여러 컬럼으로 구성된 복합 키일 때, 그 중 일부 키에만 종속되는 속성을 의미한다. 이는 테이블 구조를 비효율적으로 만들고, 변경 시 불필요한 중복과 오류를 야기한다.
예를 들어 다음과 같은 테이블을 생각해보자.
| StudentID | CourseID | StudentName | CourseName | Grade |
| 1001 | CS101 | Alice | 컴퓨터기초 | A |
이 테이블에서 기본 키는 (StudentID, CourseID)이다. 그러나 StudentName은 StudentID에만, CourseName은 CourseID에만 종속된다. 즉, 이들은 전체 키가 아닌 부분 키에 종속되어 있으므로 제2형 정규화를 위반하고 있다.
이를 2NF로 정규화하려면 종속된 속성을 별도의 테이블로 분리한다:
- 학생 정보 테이블: (StudentID, StudentName)
- 강좌 정보 테이블: (CourseID, CourseName)
- 수강 기록 테이블: (StudentID, CourseID, Grade)
이렇게 분리하면 책임과 정보의 소유가 명확히 구분되고, 중복도 줄어든다. 이러한 정규화 방식은 객체지향 프로그래밍에서의 클래스 분리 원칙과 매우 유사하다.
2NF와 클래스 분리의 연결점
2NF의 핵심은 "모든 비주요 속성은 전체 키에만 의존해야 한다"는 원칙이다. 객체지향에서 말하는 클래스 분리 역시, 한 클래스가 여러 맥락의 데이터를 동시에 다루지 않아야 하며, 각 데이터는 본래 속한 클래스에서 관리되어야 한다는 원칙을 내포하고 있다.
클래스 내부에 여러 책임이 섞여 있을 경우, 마치 부분 함수 종속처럼 불필요한 참조와 결합도를 초래한다. 결과적으로 코드 유지보수가 어려워지고, 각 데이터의 독립적인 변경이 불가능해진다.
비정규화된 클래스 예시
Unity 프로젝트에서 흔히 볼 수 있는 클래스 예시이다.
public class PlayerProfile
{
public int Id;
public string Name;
public string Email;
public string EquippedWeapon;
public int WeaponDamage;
public void PrintProfile()
{
Debug.Log($"{Name} ({Email}) uses {EquippedWeapon} with {WeaponDamage} damage");
}
}
이 클래스는 플레이어 정보와 무기 정보가 한 클래스 안에 섞여 있다. 이는 마치 StudentName과 CourseName이 한 테이블에 있는 것과 같다. 만약 무기 시스템이 독립적으로 발전하거나, 무기 교체 기능이 추가된다면 이 클래스는 불필요하게 변경될 것이다.
리팩토링: 클래스 분리 적용
제2형 정규화를 따라 책임을 분리해보면 다음과 같은 구조가 나온다:
public class PlayerInfo
{
public int Id;
public string Name;
public string Email;
public void PrintInfo()
{
Debug.Log($"{Name} ({Email})");
}
}
public class Weapon
{
public string Name;
public int Damage;
public void PrintWeaponInfo()
{
Debug.Log($"{Name} with {Damage} damage");
}
}
public class PlayerProfile
{
public PlayerInfo Info;
public Weapon EquippedWeapon;
public void PrintProfile()
{
Info.PrintInfo();
EquippedWeapon.PrintWeaponInfo();
}
}
이렇게 분리하면 각 클래스는 본질적인 데이터와 책임만을 가지며, 확장과 테스트가 독립적으로 가능해진다. 예를 들어 무기 종류를 추가하거나, 이메일 형식을 검증하는 등의 작업은 각각의 클래스 내부에서만 이루어진다.
결론
제2형 정규화는 부분 종속을 제거함으로써 데이터의 응집도를 높이고 중복을 제거한다. 이 개념은 객체지향 프로그래밍에서의 클래스 분리와 맞닿아 있으며, 책임과 데이터 소유권을 분리함으로써 유지보수성과 확장성을 확보하는 데 기여한다. 데이터이든 코드이든, 각 요소는 전체 맥락 속에서 의미 있는 위치를 가져야 하며, 불필요하게 섞여 있는 책임은 정규화와 리팩토링을 통해 분리하는 것이 바람직하다.
'소프트웨어 공학 > 아키텍처 및 구조론' 카테고리의 다른 글
| 제5정규화(5NF)와 ORM 구조 설계 (0) | 2025.04.10 |
|---|---|
| 제4정규화(4NF)의 원칙과 의존성 주입의 구조화 (0) | 2025.04.09 |
| 제3정규화(3NF)의 원칙과 필드 선언의 정제 (0) | 2025.04.08 |
| 제1형 정규화(1NF)와 단일책임원칙을 활용한 리팩토링 (0) | 2025.04.04 |
| 게임환경과 다각적 구조론 (0) | 2024.12.29 |