핵심
좋은 제약 설계는 규칙을 많이 붙이는 일이 아니라 DB가 허용할 상태를 먼저 좁히고, 나중에 제약을 추가하거나 바꿀 때는 기존 데이터와 파급 효과를 먼저 확인하는 것입니다.
입력 시점 방어
PK · UNIQUE · NOT NULL · CHECK · FK로 허용 상태를 좁힌다

잘못된 식별, 빈 값, 범위 오류, 고아 관계를 애플리케이션 버그보다 먼저 DB가 막습니다.

변경 시점 검증
기존 데이터 검사와 삭제 정책 통제로 운영 리스크를 줄인다

제약 추가 실패와 연쇄 삭제를 피하려면 ALTER TABLE 이전에 현재 상태부터 확인해야 합니다.

1

처음 테이블을 설계할 때

식별, 값, 관계를 DB 기본선으로 먼저 고정합니다.

식별
PK는 오래 유지될 값으로 두고, 업무 값은 UNIQUE로 분리

이메일이나 주민번호가 바뀌어도 조인 기준과 참조 대상은 흔들리지 않습니다.

존재·범위
필수값은 NOT NULL, 도메인 규칙은 CHECK로 막기

age >= 0 같은 규칙을 DB가 직접 검사하면 NULL 분기와 말이 안 되는 값이 초기에 사라집니다.

관계
테이블 연결은 FK로 보장하고, 관계 무결성을 코드에만 맡기지 않기

직접 SQL 실행이나 배치 오류가 있어도 부모 없는 자식 행이 남지 않도록 합니다.

2

운영 중 제약을 추가하거나 바꿀 때

변경 전에 현재 데이터와 삭제 파급 범위를 먼저 봅니다.

추가 전
기존 데이터부터 검사한 뒤 제약을 건다

NULL, 중복, 고아 행이 남아 있으면 제약 추가 단계에서 바로 기존 데이터가 제약을 위반합니다 오류가 납니다.

삭제 정책
CASCADE는 예외적으로만 쓰고, 기본은 보수적으로 시작

삭제 한 번이 연쇄 삭제로 번지지 않도록 RESTRICT, SET NULL, 소프트 삭제를 먼저 검토합니다.

운영성
제약 이름을 명시해서 어떤 규칙이 깨졌는지 바로 보이게 하기

장애 분석, 데이터 수정, 스키마 변경 때 실패한 제약을 즉시 추적할 수 있습니다.

정리: 제약 조건 설계는 “무엇을 허용할지”를 입력 시점에 좁히고, “언제 안전하게 바꿀지”를 운영 시점에 검증하는 작업입니다. 그래서 좋은 스키마는 데이터가 깨진 뒤 복구하기보다, 애초에 깨지기 어렵게 만듭니다.