개발자 팁스키마 설계 › 정규화를 어디까지 할 것인가 — 3NF 이후의 판단

정규화를 어디까지 할 것인가 — 3NF 이후의 판단

2026-08-28 · 스키마 설계
한 줄 요약

정규화는 규칙이 아니라 트레이드오프다. 언제 비정규화가 정당화되는지의 기준.

정규화가 해결하는 문제

정규화의 목적은 중복 제거를 통한 이상(anomaly) 방지다.

같은 정보가 여러 곳에 있으면:

3NF까지 가면 이 세 문제의 대부분이 해소된다.

3NF까지의 요약

| 단계 | 조건 |

|---|---|

| 1NF | 각 칸에 원자값 하나 (배열·콤마 목록 없음) |

| 2NF | 1NF + 부분 함수 종속 제거 (복합 키의 일부에만 의존하는 컬럼 분리) |

| 3NF | 2NF + 이행 종속 제거 (키가 아닌 컬럼에 의존하는 컬럼 분리) |

실무에서 대부분의 스키마는 3NF를 목표로 시작하면 충분하다.

비정규화가 정당화되는 경우

정규화된 스키마의 대가는 조인이다. 조회 시 여러 테이블을 합쳐야 한다.

비정규화를 고려할 조건:

  1. 실측된 성능 문제가 있다 — 예상이 아니라 측정치
  2. 조회가 쓰기보다 압도적으로 많다
  3. 조인 대상이 거의 변하지 않는다
  4. 인덱스·쿼리 개선으로 해결되지 않았다

4번이 중요하다. 대부분의 조인 성능 문제는 인덱스나 쿼리 구조로 해결된다. 비정규화는 그다음이다.

비정규화의 형태

1. 컬럼 복제

자주 조인하는 값을 복사해 둔다.

```

orders.user_name -- users에서 복사

```

갱신 경로 관리가 필요하다. 사용자가 이름을 바꾸면 어떻게 할 것인가?

여기서 판단이 갈린다. 주문 시점의 이름을 보존해야 한다면 이건 비정규화가 아니라 의도적 스냅샷이다. 이 경우 오히려 정규화된 참조가 잘못된 설계다.

2. 집계 컬럼

```

posts.comment_count

```

매번 세는 대신 저장한다. 갱신 누락 시 값이 틀어지므로, 정기적으로 재계산하는 배치를 함께 두는 경우가 많다.

3. 조회 전용 테이블

원본은 정규화된 채로 두고, 조회용 구조를 별도로 만든다. 동기화 지연을 허용할 수 있을 때 쓴다.

관리 방법을 함께 정한다

비정규화를 결정했다면 다음을 문서로 남긴다.

```markdown

비정규화: orders.user_name

```

갱신 정책과 불일치 허용 범위가 핵심이다. 이게 명시되지 않으면 나중에 "이 값이 왜 다르지"에서 며칠이 사라진다.

시작 시점의 선택

초기 설계에서는 정규화 쪽에서 시작하는 편이 안전하다. 이유는 성능이 아니라 변경 가능성이다.

접근 패턴이 확정되기 전에 비정규화하면, 패턴이 바뀔 때 구조 전체를 손봐야 한다.

최종 수정 2026-08-28

자주 묻는 질문

정규화를 무조건 해야 하나요?

기본적으로 3NF까지는 시작점으로 삼되, 실측된 성능 문제가 있을 때 선택적으로 비정규화하는 순서가 일반적입니다.

비정규화하면 데이터 불일치가 생기지 않나요?

생깁니다. 그래서 갱신 경로를 하나로 좁히거나 배치로 동기화하는 등 관리 방법을 함께 정해야 합니다.

처음부터 비정규화 설계로 시작해도 되나요?

접근 패턴이 확정된 경우에는 가능하지만, 초기에는 대개 패턴이 바뀝니다.

DB Linker로 지금 시작하기

AI 채팅으로 데이터베이스를 조회·관리하는 로컬 전용 개발자 도구. 자체 서버 없이 이용자의 기기에서만 동작합니다.

App Store에서 받기 →

안내

이 글은 일반적인 데이터베이스 관리 원칙과 개발 관행을 다루는 콘텐츠이며, 특정 프로젝트·프로덕션 환경에 대한 전문적 조언을 대체하지 않습니다. 구체적 버전·수치가 언급되더라도 실제 사용 중인 도구·버전에서 반드시 재확인하시기 바랍니다.

글 중 일부는 AI 도구의 도움을 받아 초안을 작성한 뒤 발행됩니다. 내용 중 사실과 다르거나 수정이 필요한 부분을 발견하시면 GitHub Issues로 알려주세요.