행의 신원과 관계의 약속: 키와 참조 무결성
데이터베이스의 키는 튜플을 구별하거나 다른 관계의 튜플을 참조하는 기준이다. 학생 이름처럼 자주 쓰이는 값도 중복될 수 있으므로, 무엇이 유일한지 설계 단계에서 명시해야 한다. 키와 참조 무결성은 조회를 편하게 만드는 부가 기능을 넘어 잘못된 데이터 상태를 거부하는 계약이다.
외래키 값의 반복은 가능하지만 참조 대상의 존재라는 약속은 지켜야 한다.
유일한 것과 최소한인 것
슈퍼키는 관계의 튜플을 유일하게 식별하는 속성 집합이다. 후보키는 그 가운데 불필요한 속성을 제거할 수 없는 최소의 슈퍼키다. 학번 하나가 학생을 구별한다면 학번과 이름의 조합도 슈퍼키일 수 있지만, 이름을 빼도 유일하므로 그 조합은 최소 후보키가 아니다.
후보키가 여러 개일 수 있고, 그중 대표로 선택한 것이 기본키다. 기본키는 복합 속성으로 이루어질 수도 있다. 예를 들어 특정 학기의 수강 기록을 학생 ID, 과목 ID, 학기 조합으로 식별할 수 있다. 후보키와 기본키의 차이는 유일성이 더 강하고 약한 차이보다 여러 가능한 식별자 중 어떤 것을 대표로 삼느냐에 있다.
SQL에서 PRIMARY KEY는 일반적으로 유일성과 NULL 금지를 함께 요구한다. UNIQUE는 다른 후보 식별자의 유일성을 표현할 수 있지만 NULL 처리 규칙은 시스템과 옵션을 확인해야 한다. 키라는 이론적 개념과 실제 DDL 제약의 동작을 연결할 때 이 차이를 살펴야 한다.
존재하지 않는 학생의 수강을 막는다
수강 테이블의 student_id를 학생 테이블의 키에 연결하는 외래키를 선언하면, 허용되지 않은 참조를 막을 수 있다. 학생 42가 없는데 student_id=42인 수강을 넣으려 하면 제약 위반이 된다. 외래키는 그 열이 유일하다는 뜻은 아니다. 같은 학생이 여러 수강 행에 등장하는 것이 정상일 수 있다.
참조되는 학생을 삭제할 때는 정책이 필요하다. 삭제를 거부할 수도 있고, 연결된 수강 행을 함께 삭제하거나 참조 값을 NULL로 바꿀 수도 있다. CASCADE가 항상 정답인 것은 아니다. 성적 기록처럼 보존이 필요한 정보와 임시 장바구니처럼 함께 없어져도 되는 정보는 다른 정책을 요구할 수 있다.
외래키가 NULL을 허용하는 경우와 복합 외래키에서 일부 값이 NULL인 경우의 의미도 확인해야 한다. 제약 검사 시점은 즉시 검사인지 커밋 때까지 연기 가능한지에 따라 다를 수 있다. 서로 참조하는 데이터를 한 트랜잭션에서 넣는 상황에서는 이 차이가 작업 순서와 실패 처리에 영향을 준다.
응용에서 조회한 뒤 존재 여부를 확인하는 것만으로 참조 무결성을 완전히 대신하기는 어렵다. 확인 직후 다른 트랜잭션이 대상을 지울 수 있기 때문이다. DB 제약은 동시에 실행되는 쓰기에서도 유효한 상태를 지키는 기반이 된다. 다만 업무의 모든 의미를 자동으로 표현하지는 않으므로 과목의 개설 상태 같은 별도 규칙도 필요하다.
키 선택에는 변경 가능성도 고려한다. 이메일처럼 자연스러운 식별자는 사람이 이해하기 쉽지만 변경이나 재사용 정책이 있을 수 있다. 대리키는 안정된 식별자를 제공할 수 있으나 업무상 중복을 막는 UNIQUE 제약을 대신하지 않는다. 각 행의 신원, 현실의 유일성, 다른 행과의 참조를 각각 명시하면 설계 의도가 훨씬 분명해진다.