JPA에서 기본키(PK) 매핑 전략은 엔티티의 식별자를 어떻게 생성하고
관리할지를 결정하는 매우 중요한 설계 요소이다.
기본키 매핑 annotation
• @Id
• @GeneratedValue
@Entity
public class MemberEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
• 기본키를 직접 할당할 때는 @Id만 사용한다.
• 자동 생성을 할 경우 @GeneratedValue를 사용하고 전략을 설정한다.
| strategy | 설명 |
| AUTO | 방언에 따라 자동 지정, strategy 기본값 |
| IDENTITY | 데이터베이스에 위임, MYSQL |
| SEQUENCE | 데이터베이스 시퀀스 오브젝트 사용, ORACLE |
| TABLE | 키 생성용 테이블 사용, 모든 DB에서 사용 |
IDENTITY 전략
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
• 기본키 생성을 데이터베이스에 위임한다.
• INSERT 이후에 PK가 결정된다.
• 영속성 컨텍스트에서 관리되려면 pk가 있어야 한다.
• 이를 위해 identity전략은 persist 시점에 INSERT쿼리가 날라간다.
• 따라서 identity 전략에서는 모아서 batch insert를 할 수 없다.
• 사실 한 트랜잭션 안에서 적은 INSERT 쿼리가 여러 번 네트워크를 통신을 탄다고 해도, 그렇게 큰 성능 차이가 나지 않는다.
SEQEUNCE 전략
• DB의 시퀀스 객체를 사용한다.
• Oracle, PostgreSQL 등 지원, MySQL 사용 불가
@SequenceGenerator(name = "MEMBER_SEQ_GENERATOR",
sequenceName = "MEMBER_SEQ",
initialValue = 1, allocationSize = 1)
@Entity
public class MemberEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
private Long id;
...
@SequenceGenerator
| 속성 | 설명 |
| name | sequenceGenerator 이름, 필수 설정 |
| sequenceName | 데이터베이스에 등록되어 있는 시퀀스 이름 |
| initialValue | 시퀀스 DDL을 생성할 때 처음 시작하는 수 지정, 기본값 1 |
| allocationSize | 시퀀스 한 번 호출에 증가하는 수 성능 최적화를 위해 사용, 기본값 50 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다 |
| catalog, schema | 데이터베이스 catalog, schema 이름 |
• 성능 최적화를 위해 allocationSize 설정으로 사전에 여러 ID를 미리 가져온다.
• 시퀀스 전략은 persist할 때 영속성 컨텍스트에 넣으려면 pk가 필요하므로, 시퀀스 call을 통해 다음 숫자를 얻어온다.
[Hibernate]
select
next value
for
member_seq_generator
• allocationSize를 크게 설정하여 미리 점유해서 persist 시점에 DB 접근 없이 영속성 컨텍스트에 바로 저장할 수 있지만, 재배포하면 메모리에서 날라가기 때문에 숫자 범위 사이에 빈 공간이 생긴다.
• 여러 웹서버가 동시에 호출하더라도, 각 서버가 숫자를 미리 확보하고 있는 것이라 문제되지 않는다.
TABLE 전략
• 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내 내는 전략
• 매 INSERT 전마다 키 테이블을 조회하거나 업데이트 해야 하고 동시성 이슈로 성능이 낮다.
• 실무에서는 될 수 있으면 사용하지 않는다.
권장하는 기본키 설계
• 기본 키는 테이블의 각 레코드를 유일하게 식별해야 하므로 다음과 같은 조건을 반드시 만족해야 한다.
| 제약 조건 | 설명 |
| NOT NULL | 값이 반드시 존재해야 함 |
| UNIQUE | 전체 테이블에서 중복되면 안 됨 |
| IMMUTABLE | 한 번 정해지면 절대 바뀌면 안 됨 |
• 미래까지 이 조건을 만족 하는 자연키를 찾기는 어렵다.
• 자연키(natural key)란 현실 세계에서 이미 존재하는 고유 식별값을 그대로 PK로 사용하는 것이다. ex) 주민등록번호, 이메일
• 유일해 보여도 시간이 지나면 변경 가능성이 존재한다.
• 개인정보보호, 식별 정책 등으로 인해 변경 or 삭제 요구 발생
실제 사례: 주민등록번호를 키로 설정하였는데, 정부 가이드에서 보안상 db에 주민번호를 저장하면 안된다고한 상황,
해당 테이블 pk만 문제가 아니라, 그 회원 테이블과 연관된 나머지 테이블이 pk를 외래키로 들고 있기 때문에 수십 개 테이블을 바꿔야 하는 문제가 발생
• 기본키는 비지니스와 상관없는 키를 쓰는게 좋다.
Long형 + 대체키 + 키 생성전략을 사용하자
• 대체키(surrogate key)는 DB 내부적으로 생성하는 무의미한 숫자 ID를 PK로 사용하는 방식이다.
id BIGINT AUTO_INCREMENT
• 의미 없는 숫자지만 유일하고, null이 아니고, 미래에도 변하지 않는다.
'springboot > jpa' 카테고리의 다른 글
| JPA 필드와 컬럼 매핑 (0) | 2025.06.23 |
|---|---|
| JPA DB 스키마 자동 생성 이상과 현실 (0) | 2025.06.22 |
| JPA 클래스와 테이블 매핑 @Entity, @Table (1) | 2025.06.22 |
| JPA 영속성 관리 (1) | 2025.06.20 |
| JPA를 왜 사용해야 하는가? (0) | 2025.06.18 |