티스토리 뷰
데이터베이스 정규화 vs 반정규화, 언제 써야 할까?
데이터베이스를 공부하다 보면 정규화와 반정규화라는 말을 자주 만나게 됩니다. 그런데 처음에는 둘이 서로 반대 개념처럼 보이면서도, 실제로는 둘 다 필요하다고 하니 더 헷갈리기 쉽습니다.
결론부터 말하면 둘 중 하나만 무조건 옳은 것은 아닙니다. 정규화는 데이터 구조를 깔끔하게 만들기 위한 기본 원칙이고, 반정규화는 조회 성능이나 사용 편의성을 위해 의도적으로 중복을 허용하는 전략입니다.
이번 글에서는 정규화가 왜 필요한지, 반정규화는 왜 생기는지, 그리고 실무에서는 언제 어떤 쪽을 선택하는지까지 흐름대로 정리해보겠습니다.
예를 들어 주문 테이블에 아래처럼 모든 정보를 한 번에 넣는다고 가정해보겠습니다.
orders
+---------+-----------+-------------+-------------+----------+
| orderId | userName | userPhone | productName | quantity |
+---------+-----------+-------------+-------------+----------+
| 1 | Kim | 010-1111 | Keyboard | 1 |
| 2 | Kim | 010-1111 | Mouse | 2 |
| 3 | Lee | 010-2222 | Monitor | 1 |
+---------+-----------+-------------+-------------+----------+
이 구조는 얼핏 보기엔 편해 보이지만 문제가 많습니다.
- Kim의 전화번호가 바뀌면 여러 행을 다 수정해야 함
- 주문이 아직 없으면 회원 정보를 넣기 애매함
- 어떤 주문이 삭제되면 회원 정보 일부가 같이 사라질 수도 있음
이런 문제를 이상 현상(Anomaly)이라고 부릅니다.
정규화는 쉽게 말해, 한 테이블에 섞여 있는 정보를 성격에 맞게 나누는 작업입니다.
위 예시라면 보통 아래처럼 나눌 수 있습니다.
- 회원 정보는
users - 주문 정보는
orders - 상품 정보는
products
이렇게 나누면,
- 회원 전화번호 수정은
users만 바꾸면 되고 - 주문 데이터는 주문답게 유지되고
- 데이터 중복도 줄어듭니다.
정규화가 잘 된 구조는 데이터 정합성에는 강하지만, 조회할 때는 여러 테이블을 JOIN해야 할 수 있습니다. 데이터량이 많아지고 조회 패턴이 복잡해지면 이 JOIN 비용이 부담이 될 수 있습니다.
그래서 실무에서는 때때로 조회 성능이나 사용 편의성을 위해 일부 중복을 허용합니다. 이게 반정규화입니다.
예를 들어 주문 목록 화면에서 매번 사용자 이름, 상품명, 배송상태를 여러 테이블에서 JOIN하는 대신, 조회에 자주 필요한 값을 일부 미리 저장해두는 식입니다.
즉, 반정규화는 설계가 엉망인 것이 아니라, 의도적으로 비용과 효율을 교환하는 전략입니다.
| 구분 | 정규화 | 반정규화 |
|---|---|---|
| 목적 | 중복 제거, 정합성 확보 | 조회 성능, 사용 편의성 향상 |
| 장점 | 수정 이상 최소화, 구조 명확 | JOIN 감소, 조회 속도 개선 가능 |
| 단점 | 조회 시 JOIN 증가 가능 | 중복 관리 비용, 정합성 위험 증가 |
| 중심 가치 | 정확하고 안정적인 데이터 | 빠르고 편한 조회 |
무엇을 더 우선할지에 따라 설계 선택이 달라질 뿐입니다.
다음 같은 경우에는 정규화를 우선하는 편이 좋습니다.
- 데이터 정합성이 매우 중요한 시스템
- 데이터 변경이 자주 일어나는 구조
- 중복 데이터가 많아질수록 관리가 어려운 경우
- 도메인 구조를 명확히 나눠야 하는 경우
예를 들어 회원, 주문, 상품, 결제처럼 서로 성격이 다른 정보는 보통 정규화해서 분리하는 것이 기본입니다.
즉, 특별한 이유가 없다면 먼저 정규화된 구조로 시작하는 것이 일반적입니다.
다음 같은 경우에는 반정규화를 고려할 수 있습니다.
- 조회가 매우 자주 일어나는 화면
- 여러 테이블 JOIN이 과도하게 많아 성능이 떨어지는 경우
- 실시간 대시보드나 통계 화면처럼 읽기 중심 서비스
- 정합성보다 조회 속도가 더 중요한 일부 영역
예를 들어 주문 목록 화면에서 자주 보여주는 회원명, 상품명, 상태 요약값 등을 일부 별도로 저장해두는 방식이 반정규화 사례가 될 수 있습니다.
다만 이때는 반드시 생각해야 합니다.
- 중복 데이터는 어떻게 동기화할 것인가?
- 값이 바뀌었을 때 어디까지 같이 갱신할 것인가?
- 조회 성능 이점이 정말 충분한가?
1) 정규화가 무조건 많을수록 좋다?
아닙니다. 과도한 분리는 오히려 사용성과 성능을 해칠 수도 있습니다.
2) 반정규화는 나쁜 설계다?
아닙니다. 근거가 있다면 충분히 좋은 전략입니다.
3) 성능이 느리면 무조건 반정규화해야 한다?
아닙니다. 인덱스, 쿼리 개선, 캐시 등 다른 방법이 먼저일 수도 있습니다.
4) JOIN이 있으면 무조건 안 좋다?
아닙니다. 관계형 DB에서 JOIN은 정상적인 기본 동작입니다.
실무에서 많이 쓰는 판단 흐름은 이렇습니다.
- 우선 정규화된 구조로 설계한다.
- 실제 조회 패턴과 성능 병목을 확인한다.
- JOIN 비용이 크고 읽기 최적화가 꼭 필요하면 반정규화를 검토한다.
- 정합성 관리 방법까지 같이 설계한다.
즉, 반정규화는 “처음부터 무조건 넣는 것”보다 필요가 확인된 뒤 도입하는 것이 더 일반적입니다.
초보 단계에서는 우선 이렇게 기억하면 충분합니다.
정규화는 데이터를 바르게 정리하는 기본 설계이고, 반정규화는 성능을 위해 의도적으로 일부 중복을 허용하는 선택입니다.
'IT > SQL·DB' 카테고리의 다른 글
| 인덱스란 무엇인가? 초보도 이해하는 원리 + 성능 차이 (0) | 2026.03.25 |
|---|---|
| 실행계획(Execution Plan) 보는 방법, 느린 쿼리 잡는 핵심 (0) | 2026.03.25 |
| 데이터베이스 Key 종류 총정리, 기본키·외래키·후보키·슈퍼키 쉽게 이해하기 (0) | 2026.03.25 |
| SQL JOIN 완벽 정리, INNER JOIN·LEFT JOIN·RIGHT JOIN 차이 한 번에 이해하기 (0) | 2026.03.24 |
| ORM이란 무엇인가? JPA 포함 개념 정리와 SQL과의 차이 (0) | 2026.03.24 |

