규칙을 깰 때: 실제 데이터베이스 정규화
Grace Collins
Solutions Engineer · Leapcell

세 가지 정규 형식은 데이터베이스 모델링에서 가장 기본적인 설계 원칙입니다. 그렇다면 세 가지 정규 형식은 정확히 무엇일까요? 그리고 실제 개발에서 우리는 그 형식을 엄격히 준수해야 할까요? 이 글에서는 이 주제에 대해 자세히 논의해 보겠습니다.
세 가지 정규 형식
1. 제1정규형 (1NF: 각 열의 원자성 보장)
제1정규형은 모든 테이블의 각 필드(열)가 원자적이어야 함을 요구합니다. 즉, 각 필드의 값은 더 이상 나눌 수 없습니다. 다시 말해, 각 필드는 단일 값만 저장할 수 있습니다. 집합, 배열 또는 반복 그룹을 포함할 수 없습니다.
예를 들어 다음 학생 테이블을 생각해 보세요.
학번 | 이름 | 전화 번호 |
---|---|---|
1 | 앨리스 | 123456789, 987654321 |
2 | 밥 | 555555555 |
이 테이블에서 전화 번호 필드는 여러 번호를 포함하고 있어 1NF의 원자성 요구 사항을 위반합니다. 1NF를 준수하려면 전화 번호를 개별 레코드로 분리하거나 새 테이블로 이동해야 합니다.
1NF를 준수한 후의 설계:
학생 테이블
학번 | 이름 |
---|---|
1 | 앨리스 |
2 | 밥 |
전화 테이블
전화 ID | 학번 | 전화 번호 |
---|---|---|
1 | 1 | 123456789 |
2 | 1 | 987654321 |
3 | 2 | 555555555 |
2. 제2정규형 (2NF: 모든 열이 전체 기본 키에 종속되어야 함)
제2정규형은 테이블이 이미 1NF를 충족하고 부분 종속성을 제거해야 함을 요구합니다. 기본 키가 아닌 필드는 전체 기본 키에 종속되어야 하며, 그 일부에만 종속되어서는 안 됩니다. 이는 일반적으로 복합 기본 키가 있는 테이블에 적용됩니다.
예를 들어 다음 OrderDetail 테이블을 생각해 보세요.
주문 ID | 제품 ID | 제품 이름 | 수량 | 단가 |
---|---|---|---|---|
1001 | A01 | 사과 | 10 | 2.5 |
1001 | A02 | 오렌지 | 5 | 3.0 |
1002 | A01 | 사과 | 7 | 2.5 |
이 테이블에서 복합 기본 키는 (주문 ID, 제품 ID)입니다. 제품 이름과 단가는 전체 기본 키가 아닌 제품 ID에만 종속되어 부분 종속성이 발생합니다. 이는 2NF를 위반합니다.
2NF를 준수한 후의 설계:
OrderDetail 테이블
주문 ID | 제품 ID | 수량 |
---|---|---|
1001 | A01 | 10 |
1001 | A02 | 5 |
1002 | A01 | 7 |
제품 테이블
제품 ID | 제품 이름 | 단가 |
---|---|---|
A01 | 사과 | 2.5 |
A02 | 오렌지 | 3.0 |
3. 제3정규형 (3NF: 이행적 종속성 제거)
제3정규형은 테이블이 이미 2NF를 충족하고 이행적 종속성을 제거해야 함을 요구합니다. 기본 키가 아닌 필드는 다른 기본 키가 아닌 필드에 종속되어서는 안 됩니다. 다시 말해, 모든 기본 키가 아닌 필드는 다른 기본 키가 아닌 필드를 통해 간접적으로가 아닌 기본 키에 직접적으로 종속되어야 합니다.
예를 들어 다음 직원 테이블을 생각해 보세요.
직원 ID | 직원 이름 | 부서 ID | 부서 이름 |
---|---|---|---|
E01 | 앨리스 | D01 | 영업 |
E02 | 밥 | D02 | 엔지니어링 |
E03 | 찰리 | D01 | 영업 |
이 테이블에서 부서 이름은 부서 ID에 종속되고, 부서 ID는 다시 기본 키(직원 ID)에 종속되어 이행적 종속성을 형성합니다. 이는 3NF를 위반합니다.
3NF를 준수한 후의 설계:
직원 테이블
직원 ID | 직원 이름 | 부서 ID |
---|---|---|
E01 | 앨리스 | D01 |
E02 | 밥 | D02 |
E03 | 찰리 | D01 |
부서 테이블
부서 ID | 부서 이름 |
---|---|
D01 | 영업 |
D02 | 엔지니어링 |
부서 정보를 별도의 테이블로 이동함으로써 이행적 종속성이 제거되고 데이터베이스 구조가 제3정규형을 준수합니다.
요약하자면, 세 가지 정규 형식은 다음과 같습니다.
- 1NF: 각 필드가 원자성 값을 갖도록 보장합니다.
- 2NF: 부분 종속성을 제거합니다. 모든 키가 아닌 필드는 전체 기본 키에 종속되어야 합니다.
- 3NF: 이행적 종속성을 제거합니다. 키가 아닌 필드는 기본 키에만 종속되어야 합니다.
세 가지 정규 형식 위반
실제로 세 가지 정규 형식 (1NF, 2NF, 3NF)을 따르면 데이터 일관성이 향상되고 중복성이 줄어들지만, 성능을 개선하고 설계를 단순화하거나 특정 비즈니스 요구 사항을 충족하기 위해 이를 위반하는 것이 유익할 수 있는 경우가 있습니다.
다음은 의도적으로 정규 형식을 위반하는 일반적인 이유와 예입니다.
성능 최적화
높은 동시성과 대규모 응용 프로그램에서 정규 형식을 엄격히 따르면 잦은 조인 작업이 발생하여 쿼리 시간과 시스템 부하가 증가할 수 있습니다. 성능을 개선하기 위해 설계자는 조인을 줄이기 위해 데이터를 비정규화할 수 있습니다.
예를 들어 Orders
및 Users
테이블이 있는 전자 상거래 시스템에서 엄격한 3NF 설계는 Orders
테이블에 User ID
만 저장하고 사용자 세부 정보를 검색하려면 조인이 필요합니다.
쿼리 성능을 개선하기 위해 Users
테이블을 조인하지 않도록 사용자 이름과 주소를 Orders
테이블에 중복으로 저장할 수 있습니다.
3NF를 위반한 후의 설계:
주문 ID | 사용자 ID | 사용자 이름 | 사용자 주소 | 주문 날짜 | 총액 |
---|---|---|---|---|---|
1001 | U01 | 앨리스 | 뉴욕 | 2025-01-01 | $500 |
1002 | U02 | 밥 | 로스앤젤레스 | 2025-01-02 | $300 |
쿼리 및 개발 단순화
엄격한 정규화는 복잡한 데이터베이스 스키마를 초래하여 개발 및 유지 관리를 더 어렵게 만들 수 있습니다. 논리를 단순화하고 개발 노력을 줄이기 위해 적절한 중복성을 도입할 수 있습니다.
예를 들어 콘텐츠 관리 시스템(CMS)에서는 일반적으로 Articles
및 Categories
테이블이 분리되어 있습니다. 카테고리 이름이 기사와 함께 자주 쿼리되는 경우 조인이 복잡성을 더합니다. 카테고리 이름을 Articles
테이블에 직접 저장하면 프런트엔드 논리가 단순화됩니다.
3NF를 위반한 후의 설계:
기사 ID | 제목 | 내용 | 카테고리 ID | 카테고리 이름 |
---|---|---|---|---|
A01 | 기사 1 | ... | C01 | 기술 |
A02 | 기사 2 | ... | C02 | 라이프스타일 |
보고 및 데이터 웨어하우징
데이터 웨어하우스 및 보고 시스템에서는 빠른 읽기 및 집계가 중요합니다. 성능을 최적화하기 위해 별 또는 눈송이 스키마와 같이 비정규화된 구조가 자주 사용됩니다. 이러한 구조는 엄격한 정규 형식을 준수하지 않습니다.
예를 들어 판매 데이터 웨어하우스에는 빠른 보고서 생성을 위해 차원 데이터가 포함된 팩트 테이블이 있을 수 있습니다.
3NF를 위반한 후의 설계:
판매 ID | 제품 ID | 제품 이름 | 카테고리 | 판매 수량 | 수익 | 판매 날짜 |
---|---|---|---|---|---|---|
S01 | P01 | 전화 | 전자 | 100 | $50000 | 2025/1/1 |
S02 | P02 | 책 | 교육 | 200 | $2000 | 2025/1/2 |
여기서 제품 이름과 카테고리를 직접 저장하면 차원 테이블과의 조인을 피할 수 있어 보고서 생성 효율성이 향상됩니다.
특별한 비즈니스 요구 사항
일부 비즈니스 시나리오에서는 특정 쿼리 또는 작업에 대한 빠른 응답이 필요합니다. 적절한 중복성은 이러한 요구 사항을 충족하는 데 도움이 됩니다.
예를 들어 실시간 거래 시스템에서 계정 잔액을 빠르게 계산하기 위해 트랜잭션 기록에서 즉석에서 계산하는 대신 사용자 테이블에 현재 잔액을 저장할 수 있습니다.
3NF를 위반한 후의 설계:
사용자 ID | 사용자 이름 | 현재 잔액 |
---|---|---|
U01 | 앨리스 | $10000 |
U02 | 밥 | $5000 |
트랜잭션 세부 정보는 다른 곳에 저장되지만 사용자 테이블에 Current Balance
를 유지하면 비용이 많이 드는 런타임 계산을 피할 수 있습니다.
읽기 및 쓰기 성능 균형 조정
읽기 작업이 쓰기 작업보다 훨씬 많은 시스템에서는 쓰기 복잡성이 증가하더라도 읽기 성능을 개선하기 위해 중복성이 허용되는 경우가 있습니다.
예를 들어 소셜 미디어 플랫폼은 사용자 프로필에 친구 수를 표시합니다. 이것을 매번 계산하는 것은 비효율적입니다. 대신 친구 수가 Users
테이블에 직접 저장됩니다.
3NF를 위반한 후의 설계:
사용자 ID | 사용자 이름 | 친구 수 |
---|---|---|
U01 | 앨리스 | 150 |
U02 | 밥 | 200 |
이를 통해 실시간 계산 없이 빠른 표시가 가능합니다.
빠른 반복 및 유연성
스타트업 또는 빠르게 진화하는 제품은 종종 유연하고 빠르게 조정 가능한 데이터베이스가 필요합니다. 과도한 정규화는 속도와 적응성을 저해할 수 있습니다. 중복 설계는 개발 속도와 민첩성을 향상시킬 수 있습니다.
예를 들어 초기 단계의 전자 상거래 플랫폼에서는 별도의 Addresses
테이블을 사용하는 대신 배송 주소를 Orders
테이블에 직접 저장할 수 있습니다.
3NF를 위반한 후의 설계:
주문 ID | 사용자 ID | 사용자 이름 | 배송 주소 | 주문 날짜 | 총액 |
---|---|---|---|---|---|
O1001 | U01 | 앨리스 | 뉴욕 | 2025/1/1 | $800 |
O1002 | U02 | 밥 | 로스앤젤레스 | 2025/1/2 | $1200 |
이렇게 하면 개발이 단순화되고 빠른 제품 출시가 지원됩니다. 필요에 따라 나중에 정규화를 적용할 수 있습니다.
복잡성 감소 및 이해도 향상
과도한 정규화는 스키마를 이해하고 유지 관리하기 어렵게 만들 수 있습니다. 적당한 중복성은 설계를 단순화하고 팀 이해도와 커뮤니케이션을 향상시킬 수 있습니다.
예를 들어 학교 관리 시스템에서 수업 정보를 여러 테이블로 분할하면 혼란스러울 수 있습니다. 단순화를 위해 수업 이름과 담임 교사를 Students
테이블에 직접 저장할 수 있습니다.
3NF를 위반한 후의 설계:
학번 | 이름 | 반 ID | 반 이름 | 담임 교사 |
---|---|---|---|---|
S01 | 앨리스 | C01 | A반 | 찰리 |
S02 | 밥 | C02 | B반 | 데이비드 |
반 이름
과 담임 교사
를 직접 저장하면 테이블 수가 줄어들고 설계가 단순화됩니다.
요약
이 글에서는 데이터베이스 설계의 세 가지 정규 형식과 그 예제를 분석했습니다. 이러한 형식은 관계형 데이터베이스 설계를 위한 기본 원칙 역할을 합니다. 그러나 실제 프로젝트에서는 성능 요구 사항, 단순화된 설계, 빠른 반복 또는 특정 비즈니스 논리로 인해 이러한 형식을 엄격히 따르지 않는 경우가 많습니다.
궁극적으로 시스템 아키텍처는 비즈니스 요구 사항, 데이터 일관성, 성능 및 개발 효율성 간의 절충입니다. 우리는 응용 프로그램 컨텍스트에 따라 실용적인 설계 결정을 내려야 합니다.
백엔드 프로젝트 호스팅을 위한 최고의 선택, Leapcell입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하십시오.
무제한 프로젝트를 무료로 배포
- 사용량에 대해서만 지불하십시오. 요청 없음, 요금 없음.
압도적인 비용 효율성
- 유휴 요금 없이 종량제로 결제합니다.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 지표 및 로깅.
손쉬운 확장성 및 고성능
- 손쉽게 높은 동시성을 처리하기 위해 자동 크기 조정.
- 운영 오버헤드가 제로이므로 빌드에만 집중하십시오.
설명서에서 자세히 알아보십시오!
X에서 저희를 팔로우하세요: @LeapcellHQ