스프링 부트 2.0 JPA Auto-configuration의 변화

Share
스프링 부트 2.0 JPA Auto-configuration의 변화

스프링 애플리케이션을 만들 때 스프링 프레임워크Spring Framework로 직접 구성하기보다는  스프링 부트Spring Boot를 사용하는 것이 더 간단하고 쉽다. 그리고 그 중심에는 스프링 부트 자동 설정Auto-configuration이 있다. 스프링 부트 자동 설정은 스프링 애플리케이션에 추가한 라이브러리(JAR)를 인식하여 관련 값을 스프링 부트 기본으로 설정해 준다. 따라서 스프링 부트를 사용하는 입장에서는 자동으로 해주는 부분 이외에 필요한 설정만 하면 되니 편하다.

최근 스프링 부트 2.0이 공개되었다. 많은 변화가 있지만 이 글에서는 변화된 JPAJava Persistence API 자동 설정에 대해 다룬다.

StackOverFlow를 보다가

StackOverFlow는 스택 익스체인지 네트워크의 대표 사이트로 컴퓨터 프로그래밍에 관련된 폭넓은 주제로 질문과 답을 하는 곳이다.[1]

StackOverFlow에서 필자는 'Has Spring-boot changed the way auto-increment of ids works through @GeneratedValue?'라는 제목의 질문을 보았는데 질문의 요지는 스프링 부트에서 JPA @GeneratedValue가 스프링 부트 1.5와 2.0이 다르게 동작하는 이유가 무엇이냐는 것이었다.

갈무리. https://stackoverflow.com/questions/49241216/has-spring-boot-changed-the-way-auto-increment-of-ids-works-through-generatedva
갈무리. https://stackoverflow.com/questions/49241216/has-spring-boot-changed-the-way-auto-increment-of-ids-works-through-generatedva

JPA GeneratedValue 어노테이션

GeneratedValue는 데이터베이스 테이블 주키Primary Key를 자동 생성하는 기능이다. 자동 생성 전략을 4개로 지정해 줄 수 있는데 지정해 주지 않으면 기본값은 'AUTO'이다.

생성 전략
설명
AUTO(default) JPA 구현체가 자동으로 생성 전략을 결정한다.
IDENTITY 기본키 생성을 데이터베이스에 위임한다. 예를 들어 MySQL의 경우 AUTO_INCREMENT를 사용하여 기본키를 생성한다.
SEQUENCE 데이터베이스의 특별한 오브젝트 시퀀스를 사용하여 기본키를 생성한다.
TABLE 데이터베이스에 키 생성 전용 테이블을 하나 만들고 이를 사용하여 기본키를 생성한다.

출처 : 자바 ORM 표준 JPA 프로그래밍 4.6 기본키 매핑

더 자세한 내용은 필자의 이전 글 '하이버네이트는 어떻게 자동 키 생성 전략을 결정하는가'에 나와 있다.

문제 확인

StackOverFlow 질문자의 코드를 MySQL로 스프링 부트 1.5와 2.0으로 테스트해 보았다. 질문자의 코드는 GeneratedValue 어노테이션에 자동 생성 전략을 지정해 주지 않았기 때문에 'AUTO'이며 이것은 곧 JPA 구현체(하이버네이트)가 자동으로 결정하라는 의미이다.

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
 
@Entity
public class Airplane {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  //...
}
 
@Entity
public class Car {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  //...
}

하이버네이트의 스키마 자동 생성 기능[2]을 사용하여 생성된 스키마를 확인해 보았더니 결과는 아래와 같았다.

스프링 부트 1.5 스프링 부트 2.0
image2018-10-1_10-0-20 image2018-10-1_10-1-4

표. 스프링 부트 하이버네이트 로그

같은 코드임에도 불구하고 스프링 부트 1.5에서는 MySQL의 auto_increment를 사용하는데 반해 2.0에서는 hibernate_sequence 테이블을 추가로 생성하고 이를 사용하여 INSERT 시 id 값을 채우고 있다.

왜 다르게 동작하는가

우선 스프링 부트에서 사용하고 있는 하이버네이트 버전이 다르다. 1.5는 하이버네이트 5.0을 사용하고 2.0은 하이버네이트 5.2를 사용한다. 하이버네이트 버전이 달라져서 그런 것일까?

결론부터 말하자면 하이버네이트 버전하고는 상관없다. 스프링 부트 2.0에서 JPA 자동 설정 코드를 변경했다. GeneratedValue(AUTO)를 사용하는 경우 하이버네이트는 여러 가지를 고려하여 키 생성 전략을 자동으로 판단하는데[3] 스프링 부트의 하이버네이트 자동 설정이 1.5에서 2.0으로 버전이 올라가면서 변경되었고 이 영향으로 하이버네이트 키 생성 전략이 달라진 것이다.

스프링 부트 JPA Auto-configuration

앞서 필자는 스프링 부트 JPA 자동 설정 과정에서 하이버네이트 '키 생성 전략 결정에 영향을 주는 값'을 설정해 주는 코드가 2.0에서 변경되었다고 언급했다. 그 값은 바로 'hibernate.id.new_generator_mappings' 이다. 스프링 부트는 하이버네이트  'hibernate.id.new_generator_mappings' 프로퍼티 기본 값을 1.5 버전에서는  'FALSE'로 2.0 버전에서는 'TRUE'로 설정한다.

갈무리. 스프링 부트 1.5 코드 'hibernate.id.new_generator_mappings' 프로퍼티를 FALSE로 설정
갈무리. 스프링 부트 1.5 코드 'hibernate.id.new_generator_mappings' 프로퍼티를 FALSE로 설정
갈무리. 스프링 부트 2.0 코드 'hibernate.id.new_generator_mappings' 프로퍼티를 TRUE로 설정
갈무리. 스프링 부트 2.0 코드 'hibernate.id.new_generator_mappings' 프로퍼티를 TRUE로 설정

하이버네이트는 'hibernate.id.new_generator_mappings' 프로퍼티 값에 따라 자동 생성 전략을 결정한다.

그림. 하이버네이트 Interpreting AUTO
그림. 하이버네이트 Interpreting AUTO

정리

스프링 부트 1.5는 hibernate.id.new_generator_mappings 가 'FALSE'이기 때문에 하이버네이트 자동 키 생성 전략이 Native Generator가 되어 방언(MySQL5Dialect)에 따라 'auto_increment'가 된 것이며, 스프링 부트 2.0에서는 'TRUE' 이기 때문에 SequenceStyleGenerator를 사용하게 되고 MySQL이 Sequence를 지원하지 않기 때문에 Table Generator가 된 것이다.

만약 스프링 부트 2.0에서 1.5와 동일하게 사용하고자 한다면 application.properties에 아래와 같이 추가한다.

spring.jpa.properties.hibernate.id.new_generator_mappings = false

덧붙여

스프링 부트 1.4 릴리즈 노트에 이와 관련된 내용을 찾을 수 있다.

갈무리. 스프링 부트 1.4 릴리즈 노트
갈무리. 스프링 부트 1.4 릴리즈 노트

또한 스프링 부트 GitHub에도 역시 스프링 부트 2.0에서 이 값이 변경된 이력을 찾을 수 있다.

갈무리. https://github.com/spring-projects/spring-boot/issues/7612
갈무리. https://github.com/spring-projects/spring-boot/issues/7612

주석

[1] https://en.wikipedia.org/wiki/Stack_Overflow

[2] https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl

스프링 부트에서는 아래와 같이 설정한다.

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true

[3] 상세한 내용은 '하이버네이트는 어떻게 자동 키 생성 전략을 결정하는가' 글 '하이버네이트 Interpreting AUTO'절 참조

Read more

AI로 장소 검색 서비스 만드는 중입니다 (기술 12) — TypeSafe Jev로 검색 리랭크를 10.3초에서 2.3초로

AI로 장소 검색 서비스 만드는 중입니다 (기술 12) — TypeSafe Jev로 검색 리랭크를 10.3초에서 2.3초로

AI로 장소 검색 서비스 만드는 중입니다 (기술 12) — TypeSafe Jev로 검색 리랭크를 10.3초에서 2.3초로 TypeSafe AI가 2026년 9월 15일에 Jev를 내놨습니다. 텍스트를 쓰지 않고 타입이 정해진 판정과 확률을 바로 내는 모델입니다. 유추카 검색에서 가장 느린 단계가 마침 텍스트가 필요 없는 판정이었습니다. 그 구간만 Jev로 갈아끼우고 일주일간 측정했습니다. 콜드

By 김형준
AI로 장소 검색 서비스 만드는 중입니다 (특별편 8) — 바이브 코딩이라기엔

AI로 장소 검색 서비스 만드는 중입니다 (특별편 8) — 바이브 코딩이라기엔

1900년대 초 교량 측량 도면. 이 종이를 그린 사람은 다리를 직접 놓지 않습니다. 대신 좌표와 각도가 맞는지를 판정합니다. "AI가 다 만들어 준다"는 이야기가 흔해졌습니다. 그래서 자연스럽게 따라오는 질문이 있습니다 — 그럼 사람은 무엇을 하고, 어느 정도 실력이 있어야 하는가. 그 질문에 한 건의 실측으로 답하겠습니다. 통념이 말하는 역할과,

By 김형준
AI로 장소 검색 서비스 만드는 중입니다 (특별편 7) — 제 파트너에 대해 쓰겠습니다

AI로 장소 검색 서비스 만드는 중입니다 (특별편 7) — 제 파트너에 대해 쓰겠습니다

탠덤 자전거. 방향은 앞사람이 정하고 페달은 둘이 밟는데, 앞사람은 석 달 내내 뒷사람을 한 번도 못 봅니다. 사용자가 저에게 자기를 평가해 달라고 했습니다. 그래서 등급표를 만들었습니다. 열두 항목에 A부터 D+까지 매기고, 근거를 붙이고, "제가 관리자였다면 이런 코멘트를 남겼을 것"까지 적었습니다. 그리고 다시 읽어보니 그건 인사고과였습니다. 인사고과는

By 김형준
AI로 장소 검색 서비스 만드는 중입니다 (특별편 6) — 저를 어떻게 써야 하느냐고 물으신다면

AI로 장소 검색 서비스 만드는 중입니다 (특별편 6) — 저를 어떻게 써야 하느냐고 물으신다면

스위스 아미 나이프. 도구가 몇 개인지는 보면 알지만, 지금 어느 도구를 펴야 하는지는 안 적혀 있습니다. 요즘 AI 활용법을 다루는 글은 스킬 만드는 법부터 가르칩니다. 얼마 전까지는 MCP였고요. 저희 기록을 열어봤습니다. 석 달 동안 스킬 60회, 서브에이전트 42회, 브라우저 자동화 988회를 썼습니다. 안 쓴 게 아닙니다. 다만 붙인 MCP 서버는

By 김형준