Schema Design Normalization Denormalization
3줄 요약
- Schema Design은 지금 화면을 저장하는 작업이 아니라 앞으로의 변경, 조회 패턴, 정합성, 운영 작업을 버티는 데이터 구조를 설계하는 일이다.
- 정규화는 중복과 갱신 이상을 줄이고, 반정규화는 읽기 성능과 단순화를 위해 의도적으로 중복을 받아들이는 선택이다.
- 좋은 백엔드 개발자는 테이블을 만들 때 API, 트랜잭션, 인덱스, 마이그레이션, 삭제 정책, 이력 요구사항을 함께 본다.
핵심 정리
- 테이블은 비즈니스 사실의 단위로 나눈다. UI 카드 하나나 DTO 하나를 그대로 테이블로 만들면 변경에 약해진다.
- 정규화는 데이터 중복을 줄이고 한 사실을 한곳에서 관리하게 만든다. 특히 회원, 주문, 결제, 재고처럼 정합성이 중요한 데이터에 중요하다.
- 반정규화는 조회 성능, 정렬, 집계, 목록 응답을 위해 사용할 수 있다. 다만 원본과 복사본의 동기화 방식이 없으면 장애의 씨앗이 된다.
- 데이터 타입은 표현 범위와 연산 의미를 반영해야 한다. 금액은 부동소수점보다 정수 최소 단위나 decimal 계열이 적합하다.
- 삭제 정책은 초기에 정해야 한다. 물리 삭제, 소프트 삭제, 익명화, 보관 기간은 법적 요구사항과 운영 복구 가능성에 영향을 준다.
- 개인 프로젝트에서도 ERD, 마이그레이션 파일, 기본 제약, 인덱스 의도를 남기면 포트폴리오 수준이 달라진다.
- 스키마 설계는 생성 시점보다 변경 시점에 실력이 드러난다. 큰 테이블에 컬럼, 제약, 인덱스, backfill을 추가할 때 lock, 배포 순서, rollback, 검증 쿼리를 함께 준비해야 한다.
- JSON, 소프트 삭제, 반정규화는 모두 “편한 예외”가 아니라 운영 책임을 동반한다. 검색/정렬/제약/복구/보관 정책을 설명할 수 없으면 기술부채가 된다.
헷갈리는 지점
- 정규화는 이론이고 실무에서는 반정규화만 중요하다고 생각하기 쉽다. 성능 이슈가 더 자주 체감되기 때문이다.
- 핵심은 정규화가 기본 안전망이고 반정규화는 근거 있는 예외라는 점이다.
- 원본 데이터의 정합성을 먼저 지키고, 병목이 확인된 조회에 중복을 도입한다.
- 소프트 삭제는 그냥
deleted_at만 추가하면 된다고 생각하기 쉽다. 구현이 간단해 보이기 때문이다.
- 핵심은 Unique 제약, 조회 조건 누락, 보관 기간, 복구 정책, 인덱스 크기까지 함께 설계해야 한다는 점이다.
- 소프트 삭제는 모든 테이블에 무조건 붙이는 기본값이 아니다.
- 컬럼은 넉넉하게 문자열로 두면 편하다고 오해하기 쉽다. 초기 개발에서는 타입 고민이 줄어들기 때문이다.
- 핵심은 타입이 데이터 검증, 인덱스 효율, 정렬 의미, 저장 공간, 쿼리 안정성을 결정한다는 점이다.
- 도메인 의미가 있는 값은 enum, check, 별도 테이블, 코드 테이블 중 적합한 방식을 선택한다.
- JSON 컬럼은 유연하니 성장 가능한 설계라고 생각하기 쉽다. 요구사항 변경에 빨리 대응할 수 있어 보이기 때문이다.
- 핵심은 핵심 도메인 필드를 JSON에 숨기면 DB 제약, 인덱스, FK, migration, 분석이 어려워진다는 점이다.
- 자주 검색하거나 정렬하거나 정합성이 중요한 값은 명시 컬럼으로 승격할 기준을 정해야 한다.
확인 질문
- 반정규화를 도입하기 전에 확인해야 하는 것은 무엇인가?
- 실제 조회 병목, 원본 데이터, 동기화 방식, 불일치 탐지 방법, 재계산 가능성, 쓰기 비용을 확인해야 한다.
- 소프트 삭제를 설계할 때 놓치기 쉬운 것은 무엇인가?
- 삭제된 데이터가 Unique 제약과 목록 조회, 인덱스 크기, 보관 정책, 개인정보 처리에 미치는 영향이다.
- 좋은 스키마 설계가 백엔드 코드에 주는 이점은 무엇인가?
- 서비스 코드가 데이터 불변식을 덜 반복하고, 잘못된 상태를 DB가 막으며, 조회와 변경 경계가 명확해진다.
- 스키마 변경을 배포 계획으로 다뤄야 하는 이유는 무엇인가?
- 운영 데이터가 이미 존재하므로 컬럼 추가, backfill, 제약 검증, 인덱스 생성이 lock, I/O, replica lag, 구버전 코드 호환성에 영향을 줄 수 있기 때문이다.