Foundry
데이터베이스
중급
핵심

반정규화

성능을 위한 의도적 중복, 트레이드오프

반정규화 (Denormalization)

핵심 개념

정규화된 테이블을 성능을 위해 의도적으로 중복시키는 것.

[정규화 상태]
orders: id, user_id, total
users:  id, name

→ 주문 조회 시 항상 JOIN 필요
  SELECT o.*, u.name
  FROM orders o
  JOIN users u ON o.user_id = u.id

[반정규화 후]
orders: id, user_id, user_name, total
                     ↑ 중복 저장!

→ JOIN 없이 바로 조회
  SELECT * FROM orders WHERE id = 1

정규화 vs 반정규화

항목정규화반정규화
중복없음의도적 중복
쓰기빠름느림 (여러 곳 업데이트)
읽기느림 (JOIN)빠름 (JOIN 제거)
정합성보장불일치 위험
적합OLTP (쓰기 중심)OLAP (읽기 중심)

반정규화 기법

1. 컬럼 추가 (가장 흔함)
   orders에 user_name 추가

2. 파생 컬럼 추가
   users에 order_count 추가
   (매번 COUNT 쿼리 대신)

3. 테이블 병합
   1:1 관계 테이블 합치기

4. 요약 테이블
   daily_sales 집계 테이블 별도 생성

실무 적용 사례

반정규화가 적합한 경우
  - 대시보드 집계 (일별 매출)
  - 검색 결과 목록 (JOIN 제거)
  - 읽기 비율 >> 쓰기 비율

반정규화를 피해야 할 경우
  - 자주 변경되는 데이터
  - 정합성이 중요한 금융 데이터
  - 쓰기가 많은 시스템

정합성 유지 방법

방법설명
트리거원본 변경 시 자동 동기화
이벤트 기반변경 이벤트 → 비동기 업데이트
배치 처리주기적 동기화 (집계 테이블)
면접에서 이렇게 나옵니다

Q.반정규화는 언제 필요하고, 어떤 위험이 있나요?

조회 성능이 병목이고 정규화된 구조로는 감당이 안 될 때입니다. 다만 정합성 유지 비용을 함께 집니다.

언제
조인이 많아 조회가 느리다게시글 목록에 작성자 이름을 함께 둔다
집계를 매번 계산하기 비싸다댓글 수를 컬럼으로 둔다
읽기가 쓰기보다 압도적으로 많다대시보드, 상품 목록
위험내용
갱신 이상원본이 바뀌었는데 사본이 그대로 남는다
갱신 비용 증가한 값을 고치려고 여러 곳을 고쳐야 한다
코드 복잡도어디를 함께 고쳐야 하는지 사람이 기억해야 한다

흔한 실수: 측정 없이 미리 반정규화하는 것. 실행 계획을 보고 조인이 실제 병목인지 확인한 뒤에 해야 합니다. 인덱스로 해결되는 경우가 훨씬 많습니다.

Q.반정규화 후 데이터 정합성은 어떻게 유지하나요?

사본을 언제 어떻게 갱신할지 정하고, 어긋남을 감지할 장치를 둡니다.

방법내용특징
같은 트랜잭션에서 함께 갱신원본과 사본을 한 번에정확하지만 쓰기가 무거워진다
변경 이벤트로 갱신원본 변경을 구독해 사본을 고친다결합이 낮다. 잠깐 어긋난다
DB 트리거DB 가 자동으로 사본을 고친다코드에 안 보여 추적이 어렵다
주기적 재계산배치로 다시 맞춘다그 사이 어긋난 채로 남는다

무엇을 쓰든 정합성 점검을 정기적으로 돌리는 것이 안전합니다. 원본과 사본을 비교해 다른 건수를 알림으로 보내면 조용히 틀어지는 것을 막습니다.

흔한 실수: 갱신 경로를 하나로 가정하는 것. 관리자 화면, 배치, 데이터 보정 스크립트처럼 사본을 모르는 경로가 늘 생깁니다. 그래서 감지 장치가 필요합니다.

Q.읽기 성능 최적화를 위해 반정규화 외에 어떤 방법이 있나요?

반정규화는 정합성 비용이 크므로 대개 마지막에 봅니다.

방법언제
인덱스 추가와 정비대부분의 느린 조회가 여기서 해결된다
커버링 인덱스테이블 접근을 없앤다
쿼리 재작성함수 적용 제거, 불필요한 조인 제거, 페이지네이션 방식 변경
캐시반복 조회가 많고 약간의 지연을 허용할 때
읽기 복제본조회 트래픽을 분산한다
구체화 뷰집계를 미리 계산해 둔다
파티셔닝큰 테이블에서 스캔 범위를 줄인다

순서가 있습니다. 먼저 재보고, 인덱스와 쿼리로 풀리는지 확인한 뒤, 캐시와 복제본을 검토하고, 그래도 안 되면 구조를 바꿉니다.

흔한 실수: 캐시부터 붙이는 것. 원인이 풀 스캔이면 캐시가 미스일 때 그대로 느리고, 무효화 문제까지 새로 떠안습니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.