JPA 에서 기본 키(PK) 매핑
JPA에서 기본 키를 매핑하는 전략(직접 할당, IDENTITY, SEQUENCE, TABLE)을 비교하고 자연 키와 대리 키의 선택 기준을 정리합니다.

JPA에서 기본키(PK) 매핑 전략
JPA를 처음 사용할 때 가졌던 궁금증이 있었다. 영속성 컨텍스트는 식별자(id)가 반드시 필요하다. 그런데 필자는 데이터베이스에서 id에 보통 AUTO_INCREMENT속성을 적용해둔다.
JPA에서 영속성 컨텍스트의 식별자를 주기 위해 id값이 필요한데, DB에서 id가 AUTO_INCREMNT로 되어있을 때는 JPA가 그 id값을 어떻게 알아낼까?
JPA가 제공하는 데이터베이스 기본 키 생성 전략을 정리해 보기로 한다.
- 직접 할당 : 기본 키를 애플리케이션에서 직접 할당한다.
- 자동 생성 : 대리 키 사용 방식
- IDENTITY : 기본 키 생성을 데이터베이스에 위임한다.
- SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
- TABLE : 키 생성 테이블을 사용한다.
직접 할당
기본키를 직접 할당하기 위해서는 @Id로 매핑하면 된다. 기본 키 직접 할당 전략은 em.persist()로 엔티티를 저장하기 전에 애플리케이션에서 기본키를 직접 할당하는 방법이다.
IDENTITY 전략
IDENTITY전략은 기본 키 생성을 데이터베이스에 위임하는 전략이다. 필자가 처음 의문을 가졌던 *DB에서 AUTO_INCREMENT값을 어떻게 가져올까?*에 대한 답이 있는 전략이다. 식별자가 생성되는 경우는 @GeneratedValue어노테이션을 사용하고 식별자 생성 전략을 설정해주어야 한다. IDENTITY 전략을 위해서는 @GeneratedValue(strategy = GenerationType.IDENTITY를 사용하면 된다. 이렇게 하면 키 값을 얻어오기 위해 데이터베이스를 추가로 조회하게 된다.
SEQUENCE 전략
SEQUENCE 전략을 사용하기 위해서는 테이블을 생성할 때 시퀀스를 생성해주어야 한다.
CREATE SEQUENCE BOARD_SEQ START WITH 1 INCREMENT BY 1;이후 엔티티에서 이 시퀀스를 사용하도록 매핑해주어야 한다.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GENERATOR")
private Long id;이렇게 사용하면 em.persist()를 호출할 때 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회한다. IDENTITY방식의 경우에는 INSERT이후 id를 가져와 했었다. SEQUENCE는 먼저 조회한 식별자를 엔티티에 할당한 후에 영속성 컨텍스트에 저장하고 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.
TABLE 전략
“테이블 전략은 키 생성 전용 테이블을 하나 만들고 이름과 값으로 사용할 수 있는 컬럼을 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.”
무엇을 선택해야 할까?
데이터베이스 기본 키는 다음 세가지 조건을 모두 만족해야 한다.
- null값은 허용하지 않는다.
- 유일해야 한다.
- 변해선 안 된다.
테이블의 기본 키를 선택하는 전략은 크게 두가지가 있다.
- 자연 키 : 비즈니스에 의미가 있는 키 (주민번호, 이메일, 전화번호)
- 대리 키 : 비즈니스와 관련 없는 임의로 만들어진 키 (대체키)
자연키 보다는 대리 키를 권장한다 예를 들어 전화번호를 자연키로 사용하기로 했다고 가정하면, 전화번호는 사람마다 없을 수도 있고 변할 수도 있다. 때문에 기본 키 세가지 조건 중에 1, 3번에 부합하지 않게 된다. 비즈니스 환경은 언제나 변한다. 유지보수 측면에서도 자연키 보다 대리키를 사용하는 것이 훨씬 좋다. JPA에서는 모든 엔티티에서 동일한 방식으로 대리 키 사용하는 것을 권장한다.
레퍼런스
자바 orm 표준 jpa 프로그래밍, 김영한
![[Spring Boot/JPA] 스프링 부트에서 JPA시작하기](/_astro/image-0.CYMVNcUy.png)
