서론
필자는 콘서트 예약 시스템 프로젝트 시작에 앞서 데이터베이스 설계를 먼저 진행했었다. 이전에 데이터베이스 정규화에 대해 학습을 했었는데 이 개념을 실제 프로젝트에 적용하고 싶었다.
정규화란, 중복을 최소화하며 데이터의 무결성을 보장 할 수 있도록 하는 방법인데 장점은 아래와 같다.
- DB 변경시 이상현상 제거
- 저장 공간의 최소화
- 데이터 구조의 안정성 및 무결성 유지
- 데이터 삽입, 삭제 및 수정 시 테이블의 재구성 필요성 감소
하지만 실제로 데이터베이스를 설계 하다보면 느끼는 문제 상황과 의문점이 생긴다. 일단 예매한 공연의 정보를 나타내는 페이지를 개발하는 상황이라고 가정해보자.
완벽하게 정규화된 bookings
테이블과 concerts
, ticket
테이블이 있다.
화면에는 당연히 콘서트 이름, 날짜 , 좌석 번호를 보여줘야 한다.
정규화 원칙에 따르자면, bookings
테이블에는 user_id
(fk) 와 ticket_id
(fk) 만 있으니 필요한 정보를 bookings
테이블 만으로는 조회할 수 없다.
해당 정보들을 조회하려면 JOIN
을 사용해야했다.
참고로 테이블간의 JOIN
연산 증가는 응답 시간 성능 저하를 일으킨다.
그래서 단지 “몇 개의 컬럼만 추가한다면 불필요한 JOIN
을 피할 수 있는데 정말 중복을 하면 안되는 걸까?” 라는 생각이 들었다.
정규화 vs 반정규화
그렇다면 우리는 언제 정규화를 해야하고 , 또 언제 반정규화를 해야할까? 데이터베이스 설계의 황금률은 명확하다.
“섣부른 최적화는 모든 악의 근원이다.” - 도널드 커누스
반정규화는 명백히 ‘최적화’의 영역이다. 따라서 아래의 원칙을 따르는 것이 현명하다.
1. 일단 정규화 하라.
설계의 시작은 언제나 정규화된 모델이어야 한다. 이것이 데이터 무결성을 지키는 가장 안전하고 기본적인 방법이다.
2. 성능을 측정하고 증명하라
JOIN
이 많다는 이유만으로 섣불리 반정규화를 적용해서는 안된다. 반드시 부하 테스트 등을 통해
특정 조회 쿼리가 실제로 시스템의 병목 지점이라는 것을 데이터로 증명해야 한다.
3. 필요한 곳만 최소한으로 적용하라.
문제가 증명되었다면, 그때 가서 문제가 될 수 있는 부분만 최소한으로 반정규화를 적용한다.
따라서 정규화된 모델을 유지하되 상황을 가정하고 테스트 해본 뒤에 반정규화를 결정하는 것이 좋다.