| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 윤성우 열혈자료구조
- datastructure
- Selection Sorting
- C programming
- 알기쉬운 알고리즘
- buffer
- ㅅ
- 윤성우의 열혈 자료구조
- Graph
- coding test
- s
- Algorithm
- 혼자 공부하는 C언어
- insertion sort
- R
- JSON
- 메모리구조
- Stack
- Serialization
- C 언어 코딩 도장
- stream
- list 컬렉션
- 이스케이프 문자
- 이것이 자바다
- Today
- Total
Engineering Note
[Database] 중간테이블은 정규화의 결과다. 확장성은 덤. 본문
[Database] 중간테이블은 정규화의 결과다. 확장성은 덤.
Software Engineer Kim 2026. 1. 1. 14:16정규화의 목적
- 데이터 중복 제거
- 데이터 일관성
- 업데이트 이상방지
비정규화
- 의도적으로 중복을 허용하는 것.
비정규화 목적
- 성능 향상
- ex)집계값 저장
예시
주문내역에서 전체 주문금액은 개별상품 가격과 상품 주문 개수를 통해서 다음 쿼리로 계산할 수 있다.
'SELECT SUM(price * quantity) FROM order_items where order_id = 1;'
하지만 자주 조회되는 경우 매번 계산하기 보다 total_amount라는 컬럼을 order 테이블에 두어 한 번에 조회할 수도 있다. 하지만 이렇게 될 경우 주문 시점에 매번 total_amount를 계산해서 insert해주어야하고, 나중에 개별상품의 주문 취소가 발생하거나, 재고 부족으로 총 주문 금액이 바뀔 경우 데이터 일관성의 문제가 발생할 수 있다.
orders:
- order_id
- total_amount(oder_items 합계와 중복)
정규화 과정
정규화가 되지 않은 order테이블
| order_id | payment_methods |
| 1 | CARD, POINT, COUPON |
| 2 | BANK_TRANSFER |
| 3 | CARD, NAVER_PAY |
문제
1. 원자값 위배(1NF 위반)
- "CARD, POINT" 하나의 셀에 여러 값
2. 쿼리 어려움
- WHERE payment_methods LIKE '%CARD%'
3. 정합성 문제
- CARD 이름 바뀌면 모든 row 찾아서 수정 => 업데이트 오류 발생 가능성 높음
이렇게 비정규화된 테이블을 정규화하기 위해 payment_method 테이블을 만들었다. 테이블을 만들지 않고 payment_methods 타입을 ENUM으로 지정해 데이터 중복문제를 해결하면서 정규화를 할 수도 있지만, 이럴경우 새로운 결제 방식이 추가되었을 때 다시 스키마를 변경해주어야 하기 때문에 확장성 측면에서 좋은 설계가 아니다.
확장성 (Extensibility): "DDL(스키마 변경) 없이 새로운 요구사항에 대응"
핵심:
- ALTER TABLE 안 함
- 컬럼 추가 안 함
- ENUM 수정 안 함
- 배포 불필요
방법:
- INSERT (데이터만 추가)
- UPDATE (설정 변경)
payment_methods
| method_id | method_name |
| 1 | CARD |
| 2 | POINT |
| 3 | COUPON |
| 4 | BANK |
| 5 | NAVERPAY |
그리고 order 테이블과 payment_methods의 관계는 N:M관계 이므로 order_payments 중간테이블을 만들어주었다.
order_payments:
| order_id | payment_method_id |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 5 |
정규화의 결과로 중간테이블이 생겼다.
또 다른 정규화의 예시
학생 - 수업 (N:M)
비정규화 테이블 (중간테이블 없음)
students
| student_id | name | courses |
| 1 | 철수 | 수학, 영어, 과학 |
| 2 | 영희 | 영어, 국어 |
정규화 (중간 테이블 사용)
sutudents:
| students_id | name |
| 1 | 철수 |
| 2 | 영희 |
courses:
| courses_id | course_name |
| 1 | 수학 |
| 2 | 영어 |
| 3 | 과학 |
| 4 | 국어 |
enrollments: 중간테이블
| student_id | course_id |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 2 | 4 |
정규화의 장점만 있는 것은 다니다.
FK로 참조하는 값의 실제 값을 구하기 위해서는 JOIN을 통해 데이터를 가져와야 하기 때문에 읽기 성능이 비정규화된 테이블보다 낮아질 수 있다.
정리
정규화
목적: 중복제거
방법: 테이블 분리
결과: 테이블 수 증가
예시: N:M -> 중간테이블
정규화 특징
- JOIN 증가
- 데이터 무결성 향상
- 저장 공간 감소
- 쓰기 빠름
- 읽기 느림(JOIN 필요)
비정규화
목적: 성능 향상
방법: 의도적 중복
결과: 중복 데이터
예시: 집계값 저장
비정규화 특징
- JOIN 감소
- 데이터 무결성 감소
- 저장 공간 증가
- 쓰기 느림 (중복 관리)
- 읽기 빠름
'Computer Science > Database' 카테고리의 다른 글
| [Database] 제약조건 공부, 유니크(복합 유니크) (0) | 2026.01.08 |
|---|---|
| [Database] 트랜잭션과 잠금(MySQL) (0) | 2026.01.01 |
| [Database] 외래키(Foreign Key) (0) | 2025.12.26 |
| [Database] 데이터베이스의 트랜잭션 처리 연산 과정 (0) | 2025.12.24 |
| [Database] FLUSH와 COMMIT 차이 (0) | 2025.10.07 |