데이터 무결성 설계
데이터 무결성 설계는 개체·키·참조·도메인·업무 규칙을 PK·UK·FK·NOT NULL·CHECK와 트랜잭션·서비스 통제로 구현하는 작업입니다. 가능한 규칙은 데이터베이스에서 일관되게 강제하고, 교차 행·교차 테이블·기간 규칙은 동시성과 우회 적재 경로까지 포함해 통제해야 합니다.
핵심 요약
무결성은 데이터가 업무 규칙에 맞게 정확하고 일관된 상태를 유지하는 성질이다. PK는 행의 유일·필수 식별, UK는 대체키 유일성, FK는 부모-자식 참조, NOT NULL·CHECK·데이터 타입은 도메인 범위를 통제한다. 여러 행의 합계·기간 중복·상태 전이처럼 선언적 제약만으로 표현하기 어려운 규칙은 트리거·서비스·배치 검증을 사용할 수 있지만, 동시 트랜잭션과 모든 입력 경로에서 같은 규칙이 적용되는지 확인해야 한다.
학습 목표
- 개체·키·참조·도메인·업무 무결성을 구분한다.
- PK·UK·FK·NOT NULL·CHECK의 역할과 한계를 설명한다.
- FK의 선택성·삭제 동작·복합키를 업무 생명주기에 맞게 설계한다.
- DB 제약과 애플리케이션 통제의 장단점 및 동시성 위험을 평가한다.
1. 무결성 유형
1.1 개체 무결성
각 테이블 행을 유일하게 식별하고 식별값이 NULL이 되지 않도록 한다. 일반적으로 PK가 구현 수단이다.
- 테이블당 주 PK는 하나지만 여러 컬럼으로 구성할 수 있다.
- PK는 UNIQUE와 NOT NULL의 의미를 함께 가진다.
- 대리키 PK를 사용해도 업무상 유일한 자연키가 사라지는 것은 아니다. 자연키는 UK나 업무 제약으로 보존한다.
1.2 키 무결성
후보키·대체식별자의 유일성을 보장한다.
회원 PK: 회원ID
대체키: 이메일주소, 외부회원번호
이메일을 대체키로 인정했다면 PK 외에 유일성 통제가 필요하다. NULL을 허용하는 UK의 중복 처리, 대소문자·공백·정규화는 DBMS와 도메인 규칙에 따라 달라지므로 실제 표현식을 검토한다.
1.3 참조 무결성
자식 FK의 비NULL 값이 부모의 PK 또는 유일키에 존재하도록 한다.
주문.고객ID → 고객.고객ID
FK 컬럼이 NULL 허용이면 “부모 없음”이 가능할 수 있다. 논리 관계가 필수라면 NOT NULL도 필요하다. 복합 FK는 컬럼 수·순서·타입을 부모 키와 맞춰야 한다.
1.4 도메인 무결성
속성 값이 정의된 타입·길이·범위·단위·허용값을 따르도록 한다.
- 데이터 타입·길이·정밀도
- NOT NULL
- CHECK 범위와 값 조합
- 코드 테이블 FK
- 명시적 기본값
기본값은 유효한 값 생성에 도움을 주지만 그 자체가 범위·참조 무결성을 보장하지 않는다.
1.5 업무·의미 무결성
단일 컬럼 제약보다 복잡한 규칙이다.
- 주문총액 = 주문라인 합계
- 같은 계약의 유효기간은 중복 금지
- 고객별 기본배송지는 정확히 한 건
- 주문상태는 허용된 순서로만 전이
- 출고수량은 주문수량을 초과할 수 없음
이 규칙은 설계 시 명시하고 DB 선언 제약, 유일 인덱스, 트리거, 서비스 트랜잭션, 직렬화·잠금, 주기 검증 중 적합한 조합으로 구현한다.
2. 제약조건의 역할
| 수단 | 강제하는 규칙 | 장점 | 한계·주의 |
|---|---|---|---|
| PRIMARY KEY | 행의 유일·필수 식별 | 중앙 강제, 참조 대상 | 업무 대체키는 별도 필요 |
| UNIQUE | 후보키·대체키 유일성 | 중복 방지 | NULL·정규화 동작 제품 차이 |
| FOREIGN KEY | 부모 존재와 참조 동작 | 우회 입력에도 적용 | 자식 FK 인덱스는 별도 판단 가능 |
| NOT NULL | 값 필수 | 단순·강력 | 업무 단계별 선택성을 고려 |
| CHECK | 한 행의 범위·조합 | 선언적·가시적 | 다른 행·테이블 참조 제한 제품 차이 |
| DEFAULT | 미지정 시 값 생성 | 입력 일관성 | 유효성·의도 자체를 검증하지 않음 |
| 트리거 | 복잡한 DB 내부 규칙 | 여러 입력 경로에 적용 가능 | 숨은 부작용·순서·성능·재귀 |
| 서비스 로직 | 업무 흐름·외부 연계 | 표현력·오류 메시지 | 우회 적재·동시성·중복 구현 위험 |
| 배치 검증 | 대량·사후 품질 점검 | 기존 데이터 탐지 | 오류를 사후에 발견 |
3. 참조 동작 설계
부모 삭제·키 변경 시 자식을 어떻게 할지 업무 생명주기로 결정한다.
| 동작 | 의미 | 적합 예 | 위험 |
|---|---|---|---|
| RESTRICT/NO ACTION | 자식이 있으면 부모 삭제 금지 | 주문이 있는 고객의 물리 삭제 금지 | 보존·익명화 정책 별도 필요 |
| CASCADE | 부모 삭제가 자식 삭제로 전파 | 종속 임시 상세, 제한된 구성 데이터 | 대량·연쇄 삭제와 감사 손실 |
| SET NULL | 자식 관계를 끊고 행 유지 | 관계가 선택적이며 부모 없이 의미 유지 | 필수 관계에는 부적합 |
| SET DEFAULT | 지정 기본 참조로 변경 | 제품·업무가 명확히 지원할 때 | “기타” 부모로 사실 왜곡 가능 |
주문·결제처럼 법적 보존이 필요한 데이터에는 고객 삭제를 CASCADE로 전파하는 것이 부적절할 수 있다. 삭제 대신 비활성화·익명화·접근 제한을 검토한다.
4. DB 통제와 애플리케이션 통제
4.1 DB 제약을 우선 검토하는 이유
- 여러 애플리케이션·배치·관리자 도구에 동일 규칙 적용
- 동시 트랜잭션에서 중앙 일관성 확보
- 데이터 사전과 DDL에 규칙이 가시적
- 위반 데이터가 저장되기 전에 차단
4.2 애플리케이션 통제가 필요한 경우
- 외부 서비스 결과와 함께 판단하는 규칙
- 복잡한 상태 전이와 사용자 권한·승인 흐름
- 여러 시스템을 아우르는 분산 트랜잭션
- 상세한 오류 메시지와 보상 작업
그러나 “먼저 SELECT로 중복 확인 후 INSERT”만 수행하면 두 세션이 동시에 통과할 수 있다. 최종 유일성은 UK 같은 DB 제약이나 적절한 동시성 제어로 보장해야 한다.
4.3 대량 적재와 제약 비활성화
성능을 이유로 제약을 비활성화하거나 지연 검증할 때는 다음을 정의한다.
- 적재 전 원천 검증
- 적재 후 전체 제약 검증
- 오류행 격리·재처리
- 제약 재활성화 실패 시 롤백
- 비활성화 시간 동안의 동시 DML 차단
제약을 껐다는 사실이 데이터 품질 책임을 없애지 않는다.
5. DDL 사례
요구:
- 주문은 반드시 존재하는 고객에 속한다.
- 주문번호 외에 채널별 외부주문번호가 유일하다.
- 주문금액은 0 이상이다.
- 주문상태는 정해진 코드만 허용한다.
아래 SQL은 무결성 매핑을 보여 주는 예시이며 데이터 타입·제약 문법은 DBMS별로 조정한다.
CREATE TABLE ORDERS (
ORDER_ID BIGINT PRIMARY KEY,
CUSTOMER_ID BIGINT NOT NULL,
CHANNEL_CODE VARCHAR(10) NOT NULL,
EXTERNAL_ORDER_NO VARCHAR(50) NOT NULL,
ORDER_AMOUNT DECIMAL(15,2) NOT NULL,
ORDER_STATUS_CODE VARCHAR(20) NOT NULL,
CONSTRAINT UK_ORDERS_EXTERNAL
UNIQUE (CHANNEL_CODE, EXTERNAL_ORDER_NO),
CONSTRAINT FK_ORDERS_CUSTOMER
FOREIGN KEY (CUSTOMER_ID) REFERENCES CUSTOMER(CUSTOMER_ID),
CONSTRAINT FK_ORDERS_STATUS
FOREIGN KEY (ORDER_STATUS_CODE)
REFERENCES ORDER_STATUS_CODE(ORDER_STATUS_CODE),
CONSTRAINT CK_ORDERS_AMOUNT
CHECK (ORDER_AMOUNT >= 0)
);
주문라인 합계=주문금액은 여러 행을 참조하므로 위 DDL만으로 자동 보장되지 않는다. 주문 확정 트랜잭션, 저장 파생값 통제, 주기 대조를 추가 설계한다.
6. 무결성 설계 절차
업무 규칙 목록화
↓
개체·키·참조·도메인·업무 무결성으로 분류
↓
PK·UK·FK·NOT NULL·CHECK로 선언 가능한 규칙 우선 매핑
↓
교차 행·상태·기간 규칙의 트랜잭션·동시성 통제 설계
↓
온라인·배치·인터페이스·관리자 우회 경로 검증
↓
정상·경계·동시·대량 적재·복구 시나리오 시험
7. 비교와 구분
| 구분 | 핵심 질문 | 대표 수단 |
|---|---|---|
| 개체 무결성 | 행을 유일·필수로 식별하는가? | PK |
| 키 무결성 | 다른 후보키의 중복을 막는가? | UK, 유일 인덱스 |
| 참조 무결성 | 자식이 유효한 부모를 참조하는가? | FK + NULL/삭제 규칙 |
| 도메인 무결성 | 값의 타입·범위·코드가 유효한가? | 타입, NOT NULL, CHECK, 코드 FK |
| 업무 무결성 | 여러 값·행·상태·기간의 규칙이 맞는가? | 제약+트랜잭션+서비스+검증 |
시험 판단 포인트
- 대리키 PK를 채택해도 업무 대체키의 유일성 규칙은 UK 등으로 보존한다.
- 필수 참조 관계는 FK 존재뿐 아니라 FK 컬럼의 NOT NULL 여부를 확인한다.
- CHECK는 일반적으로 한 행의 값 범위·조합에 적합하고 교차 행 규칙은 추가 통제가 필요하다.
- CASCADE가 편리하다는 이유만으로 보존 데이터에 적용하지 않는다.
- 애플리케이션 사전 조회만으로 동시 중복을 완전히 방지할 수 없다.
자주 틀리는 부분
- PK가 있으면 모든 업무 중복이 막힌다고 본다.
- FK 컬럼이 NULL이면 참조 검사에서 제외될 수 있다는 점을 놓친다.
- 화면 입력 검증을 모든 데이터 경로의 무결성으로 간주한다.
- 기본값을 CHECK나 코드 FK의 대체물로 사용한다.
- 제약 비활성화 후 검증·오류 격리 없이 운영 데이터를 공개한다.
개념 확인 문제
문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.
01객관식 대리키 회원ID가 PK이고 이메일도 업무상 유일해야 한다. 필요한 설계는? A. PK만 있으면 충분하다. B. 이메일에 업무 규칙에 맞는 UNIQUE와 필수성·정규화 통제를 추가한다. C. 이메일을 자유문자 메모로 저장한다. D. 모든 이메일을 같은 기본값으로 둔다.
정답: B
- B: 대리키는 행 식별을 담당하고 이메일이라는 후보키의 업무 유일성은 별도 UK로 보존한다. NULL 허용, 대소문자, 앞뒤 공백, 정규화된 비교값도 정의해야 한다.
- A: 서로 다른 회원ID로 같은 이메일을 여러 번 등록할 수 있다.
- C, D: 도메인·유일성 규칙을 파괴한다.
02객관식 주문은 반드시 고객에 속해야 한다. ORDERS.CUSTOMERID에 FK만 있고 NULL을 허용한다면? A. 고객 없는 주문을 완전히 방지한다. B. NULL 주문은 FK 검사를 피할 수 있으므로 NOT NULL이 추가로 필요하다. C. FK가 PK를 자동 생성한다. D. 고객 삭제가 항상 CASCADE된다.
정답: B
- B: 많은 DBMS에서 NULL FK는 부모 존재 검사를 요구하지 않는다. 필수 관계라면 NOT NULL이 필요하다.
- A: NULL 값이 허용되어 고객 없는 주문이 가능하다.
- C: FK는 자식 PK를 생성하지 않는다.
- D: 삭제 동작은 별도로 정의하며 기본이 CASCADE인 것은 아니다.
03참·거짓 “애플리케이션에서 INSERT 전에 중복 SELECT를 수행하면 동시 세션에서도 유일성이 완전히 보장되므로 DB UNIQUE 제약은 불필요하다.”
정답: 거짓
두 세션이 동시에 중복이 없음을 조회한 뒤 같은 값을 INSERT할 수 있다. 최종 유일성은 UNIQUE 제약이나 동등한 직렬화 통제로 보장해야 한다. 애플리케이션 검사는 사용자 메시지 개선에 사용할 수 있지만 DB 제약을 대체하지 않는다.
04DDL 설계 수량은 1 이상, 상품은 반드시 존재, 주문번호+라인순번은 유일이라는 주문라인 테이블의 핵심 제약을 작성하시오.
모범 답안
CREATE TABLE ORDER_LINE (
ORDER_ID BIGINT NOT NULL,
LINE_NO INTEGER NOT NULL,
PRODUCT_ID BIGINT NOT NULL,
QUANTITY INTEGER NOT NULL,
CONSTRAINT PK_ORDER_LINE
PRIMARY KEY (ORDER_ID, LINE_NO),
CONSTRAINT FK_ORDER_LINE_ORDER
FOREIGN KEY (ORDER_ID) REFERENCES ORDERS(ORDER_ID),
CONSTRAINT FK_ORDER_LINE_PRODUCT
FOREIGN KEY (PRODUCT_ID) REFERENCES PRODUCT(PRODUCT_ID),
CONSTRAINT CK_ORDER_LINE_QUANTITY
CHECK (QUANTITY >= 1)
);
요구에는 상품 존재뿐 아니라 주문 존재도 자연스럽게 필요하므로 주문 FK를 포함했다. 라인번호 범위나 동일 상품 중복 허용 여부는 별도 업무 규칙이다.
05사례 판단 고객별 기본배송지는 정확히 한 건이어야 한다. 단순히 각 배송지 행에 기본여부 CHECK(Y/N)만 두면 충분한지 판단하고 추가 통제를 제시하시오.
모범 답안
충분하지 않다. CHECK는 각 행의 값이 Y 또는 N인지 확인할 뿐 한 고객에 Y가 여러 건 존재하는 것을 막지 못한다. 다음 통제를 조합한다.
- 고객별
기본여부='Y'조건부 유일성(제품이 지원하는 부분/조건부 유일 인덱스 등) - 기본 배송지 변경을 한 트랜잭션에서 이전 Y→N, 새 N→Y로 처리
- 고객에게 배송지가 존재한다면 최소 한 건은 Y라는 규칙 검증
- 동시 변경 시 잠금·직렬화 또는 전용 서비스 API
- 주기적으로 고객별 Y 건수가 1인지 대조
제품별 조건부 유일성 기능이 다르면 별도 테이블에 고객번호 PK, 기본배송지ID FK를 두는 대안도 검토할 수 있다.