테이블 기본키(Primary Key) 선택 전략: Natural Key vs Surrogate Key
데이터베이스 설계에서 기본키 선택은 성능과 데이터 무결성에 큰 영향을 미치는 중요한 결정입니다. 크게 두 가지 접근 방식이 있는데, 바로 자연키(Natural Key)와 대리키(Surrogate Key)입니다.
자연키(Natural Key)
자연키는 데이터 자체에 존재하는 속성을 기본키로 사용하는 방식입니다.
특징:
- 비즈니스 데이터에서 자연적으로 발생하는 고유한 값 사용
- 예: 주민등록번호, 이메일 주소, ISBN 등
- 추가 컬럼이 필요하지 않아 저장 공간 절약 가능
장점:
- 자연적인 의미를 가져 직관적인 이해 가능
- 별도의 키 생성 로직이 필요 없음
- 데이터 중복 방지에 도움
단점:
- 변경 가능성 있음 (이메일 주소나 전화번호 등이 변경될 수 있음)
- 복합키가 필요한 경우 쿼리 복잡성 증가
- 외래키 참조 시 오버헤드 발생 가능
- 비즈니스 규칙 변경에 취약
대리키(Surrogate Key)
대리키는 실제 데이터와는 관련 없는 인공적으로 생성된 값을 기본키로 사용하는 방식입니다.
특징:
- 자동 증가 정수(Auto-increment), UUID, 시퀀스 등 사용
- 데이터의 실제 속성과는 무관한 값
- 시스템에 의해 자동 생성 및 관리
장점:
- 변경되지 않음 (불변성)
- 단순하고 일관된 키 구조
- 인덱싱 및 조인 성능이 우수 (특히 정수형)
- 비즈니스 규칙 변경에 영향받지 않음
단점:
- 의미 없는 값으로 직관성 떨어짐
- 추가 저장 공간 필요
- UUID 사용 시 인덱스 크기 증가로 성능 저하 가능성
정수형 vs UUID 기반 대리키
대리키를 사용할 때 자주 고려되는 두 가지 옵션에 대해 자세히 살펴보겠습니다.
정수형 기본키 (Auto-increment)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL
);
장점:
- 저장 공간 효율적 (일반적으로 4바이트)
- 인덱스 성능 최적화
- 순차적 삽입으로 인한 페이지 분할 최소화
- 직관적인 디버깅 및 관리
단점:
- 분산 시스템에서 생성 복잡
- 값으로부터 정보 유추 가능 (보안 이슈)
- 시퀀스 고갈 가능성 (특히 INT 타입 사용 시)
UUID 기반 기본키
CREATE TABLE products (
id CHAR(36) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL
);
// Java에서 UUID 생성 예시
String productId = UUID.randomUUID().toString();
장점:
- 분산 시스템에 적합 (충돌 가능성 극히 낮음)
- 데이터베이스 간 마이그레이션 용이
- 보안 강화 (순차적 예측 불가)
- ID 생성을 애플리케이션에서 처리 가능
단점:
- 저장 공간 비효율적 (16바이트 또는 문자열 36바이트)
- 인덱스 성능 저하
- 인간 가독성 낮음
- 랜덤 삽입으로 인한 페이지 분할 가능성 증가
기본키 선택 가이드라인
-
시스템 규모와 분산 여부 고려
- 단일 데이터베이스: Auto-increment 정수형이 성능상 유리
- 분산 시스템: UUID나 Snowflake ID 같은 대안 고려
-
데이터 변경 가능성 분석
- 변경 가능성이 있는 비즈니스 속성은 자연키로 부적합
- 불변성이 보장되어야 기본키로 적합
-
성능 요구사항 평가
- 고성능이 필요한 대용량 시스템: 정수형 대리키 선호
- 조인 작업이 많은 경우: 작은 크기의 키가 유리
-
비즈니스 요구사항 고려
- 외부 시스템과의 통합 필요성
- 보안 및 개인정보 보호 요구사항