데이터베이스 키 제약을 고려한 식별자 설계
데이터베이스 키의 유일성·최소성·비NULL성과 변경 가능성, 크기, 복잡성을 바탕으로 기본 키와 대리 키를 설계하는 방법
2026-08-14 · 최초 발행 2025-08-10
레코드 식별자는 관계와 변경 비용을 함께 결정한다
키는 테이블의 레코드를 구분하고 테이블 사이의 관계를 연결하는 필드, 또는 필드 집합이다. 기본 키는 한 테이블 안에서 레코드를 고유하게 식별하며, 외래 키는 다른 테이블의 기본 키를 참조한다.
후보 키는 기본 키가 될 수 있는 속성 또는 속성 집합이고, 슈퍼 키는 레코드를 고유하게 식별할 수 있는 속성 조합이다. 후보 키 가운데 기본 키로 선택되지 않은 것은 대체 키가 된다. 이 구분은 단순한 용어 정리에 그치지 않는다. 어떤 값을 키로 채택하는지에 따라 입력 검증, 인덱스, 조인, 데이터 변경의 비용이 달라진다.
후보 키가 충족해야 하는 조건
유일한 값으로 레코드를 구분해야 한다
키 값은 테이블 안에서 중복될 수 없다. 따라서 데이터를 삽입할 때 중복 검사가 필요하고, 유일성을 보장하는 인덱스는 추가 저장공간을 사용한다. 기존 데이터를 변경할 때도 유일성 검증 오버헤드가 발생한다.
주민등록번호를 기본 키로 사용한다면 동일한 주민등록번호를 가진 두 사람을 시스템에 등록할 수 없다. 식별자로서의 역할은 분명하지만, 그 값이 실제 운영 환경에서 적절한 키인지와는 별도로 검토해야 한다.
식별에 필요하지 않은 속성은 키에서 제외한다
후보 키는 최소한의 속성으로 구성되어야 한다. 이미 하나의 속성만으로 식별이 가능한데 다른 속성을 더하면, 불필요한 키 구성은 효율과 관리 편의성을 떨어뜨릴 수 있다.
예를 들어 학생 테이블에서 학번+이름 조합이 레코드를 식별하더라도 학번만으로 식별할 수 있다면, 최소성을 만족하는 키는 학번이다. 불필요한 속성이 포함된 키는 관리 복잡성을 높이고 성능 저하로 이어질 수 있다.
키에는 NULL이 들어갈 수 없다
키 속성은 NULL 값을 가질 수 없다. 데이터 입력 과정에서 NULL 여부를 확인해야 하며, 무결성을 보장하는 메커니즘과 예외 처리 로직도 필요하다.
회원번호가 회원 테이블의 기본 키라면 모든 회원은 회원번호를 반드시 가져야 한다. 식별자가 비어 있으면 해당 레코드를 다른 레코드와 구분하거나 참조할 기준도 사라진다.
시간이 지나도 감당할 수 있는 키인가
기본 키는 변경되지 않아야 하며, 시간이 지나도 값이 바뀔 가능성이 낮아야 한다. 키가 바뀌면 참조 무결성 문제가 생기고 관련 테이블을 연쇄적으로 업데이트해야 한다. 이력 관리도 복잡해진다.
주민등록번호를 기본 키로 사용하는 시스템에서 그 번호가 변경되면 관련 테이블 전반에 연쇄 업데이트가 필요하다. 이메일 주소를 기본 키로 사용한 경우에도 사용자가 이메일을 바꾸면 참조 테이블의 갱신 부담이 생긴다. 불안정한 키는 인덱스 재구성 필요성을 높이고 데이터 일관성을 유지하기 어렵게 만든다.
키의 크기도 설계 대상이다. 큰 키는 인덱스 크기를 키우고 조인 연산 성능을 낮추며 저장공간 효율을 떨어뜨릴 수 있다. UUID(36자)와 시퀀스 숫자(4바이트)는 이런 차이를 검토할 때 비교할 수 있는 예다.
복잡한 키 역시 개발과 유지보수의 부담이 된다. 여러 필드를 조합한 복합 키는 개발자가 처리해야 할 조건을 늘리고, 실수 가능성과 시스템 확장성의 제약을 함께 키울 수 있다.
자연 키와 대리 키를 나누어 보는 이유
자연 키는 업무 도메인에 이미 존재하는 속성을 사용하는 방식이다. 주민등록번호, 이메일, 상품코드가 여기에 해당한다. 의미 있는 값을 그대로 쓸 수 있고 추가 인덱스가 필요 없다는 장점이 있지만, 값이 바뀔 가능성과 크기 제약을 함께 가진다.
대리 키는 시스템이 생성하는 인공 식별자다. 자동 증가 정수와 UUID가 대표적이다. 변경되지 않고 구조가 단순하며 성능 최적화에 유리할 수 있다. 반면 추가 저장공간이 필요하고 업무적 의미는 담지 않는다.
복합 키는 여러 필드 조합으로 이루어진 키다. 자연 키를 활용하면서 추가 인덱스 역할을 할 수 있지만, 조인 성능과 관리 복잡성의 부담이 따른다. 사용할 때는 필드 수를 최소화하고, 변경 가능성이 낮은 필드를 선택하며, 작은 데이터 타입을 우선하는 편이 낫다.
업무 값과 내부 식별자를 분리한 사례
이메일을 기본 키로 둔 회원 시스템에서는 이메일 변경 요청이 들어올 때 관련 테이블을 모두 업데이트해야 한다. 이메일 길이는 인덱스 크기를 늘리고 조인 성능에도 영향을 준다. 회원ID 같은 대리 키를 도입하고 이메일은 유니크 인덱스로 관리하면 이메일 변경 시 단일 테이블만 업데이트할 수 있다.
주문상세 테이블의 기본 키로 주문번호와 상품코드 조합을 사용하면 외래 키 참조가 복잡해지고 인덱스 크기와 조인 비용도 커진다. 주문상세ID를 대리 키로 두고 주문번호+상품코드에는 유니크 인덱스를 설정하면, 데이터 액세스 패턴에 맞춰 인덱스를 최적화할 수 있다.
부서코드나 직급코드처럼 업무 코드를 키로 쓰는 경우에는 조직 구조가 바뀔 때 코드 체계도 변경해야 할 수 있다. 이때 데이터 마이그레이션이 어려워진다. 내부적으로 대리 키를 사용하고 업무 코드를 별도 필드로 관리하면 코드 체계와 실제 키를 분리할 수 있다.
설계 단계에서 확인할 운영 기준
대리 키는 단순 정수형 ID 또는 UUID를 사용해 우선 검토할 수 있다. 업무 요구사항이 바뀌어도 내부 식별자에 미치는 영향을 줄이고, 자연 키는 유니크 인덱스로 관리하는 방식이다.
키의 데이터 타입은 가능한 작게 선택한다. INT와 BIGINT의 선택, 문자열 키의 길이, 복합 키의 필드 수는 인덱스와 조인 비용에 직접 연결된다.
키로 쓰려는 필드가 변경될 가능성도 먼저 평가해야 한다. 변경 가능한 값은 키로 사용하는 일을 피하고, 불가피하다면 변경 관리 전략을 마련해야 한다. 시퀀스나 자동 증가 메커니즘을 활용하고 키 생성 로직을 중앙화하며 키 관리 정책을 문서화하는 방식도 함께 고려할 수 있다.
키 설계는 모델링 초기에 결정되지만, 이후의 성능·확장성·유지보수성까지 이어진다. 대리 키와 업무 값을 어떻게 분리할지, 복합 키가 실제로 필요한지, 값의 변경을 감당할 수 있는지를 데이터 구조가 굳기 전에 판단해야 한다.