목차
개요
JPA의 구현체 중 하나인 하이버네이트는 다양한 기능을 제공하는데 그 중 엔티티만 등록해놓으면 DDL(Data Definition Language)을 자동으로 작성하여 테이블을 생성하거나 수정해주는 ddl-auto
라는 설정이 있다. JPA에 대해 아는 것이 거의 없던 처음에는 DDL을 자동으로 작성해주는 아주 편리한 기능이라고만 생각했는데, JPA를 배워가면서 마냥 편리한 기능이 아니라 잘못 다루면 돌이킬 수 없는 결과를 가져오는 아주 위험한(?) 기능이라는 것을 느끼게 되었다.
이 포스트에서는 JPA 하이버네이트에서 제공하는 ddl-auto
의 종류와 기능, 그리고 주의 사항에 대해서 정리하려고 한다.
ddl-auto
속성의 종류
ddl-auto
에는 아래와 같이 5가지 종류의 속성이 있다.
create
create-drop
update
validate
none
(default)
create
create
는 단어 그대로 엔티티로 등록된 클래스와 매핑되는 테이블을 자동으로 생성(create)해준다. 이 과정에서 기존에 해당 클래스와 매핑되는 테이블이 존재한다면 기존 테이블을 삭제(drop)하고 테이블을 생성한다.
create
옵션을 사용하면 아래와 같은 DDL이 자동으로 작성되어 DB에 반영된다.
create-drop
create-drop
은 create
와 비슷하게 엔티티로 등록된 클래스와 매핑되는 테이블이 존재한다면 기존 테이블을 삭제하고 자동으로 테이블을 생성해주는 것은 똑같지만, 애플리케이션이 종료될 때 테이블을 삭제한다는 차이가 있다.
create-drop
옵션을 사용하면 아래와 같이 애플리케이션이 시작될 땐 create
와 동일한 DDL이 작성되지만, 애플리케이션이 종료될 때 테이블을 삭제하게 된다.
update
update
는 엔티티로 등록된 클래스와 매핑되는 테이블이 없으면 새로 생성하는 것은 create
와 동일하지만 기존 테이블이 존재한다면 위의 두 경우와 달리 테이블의 컬럼을 변경하게 된다.
하지만, 일반적으로 생각하는 update와는 달리 모든 변경사항을 반영하는 것이 아니다. 기존에 존재하는 컬럼의 속성(nullable, 크기, 데이터 타입 등)은 건드리지 않고, 새로운 컬럼이 추가되는 변경사항만 반영한다. 가령, 어떠한 엔티티 클래스의 String 필드를 Int로 변경하더라도 해당 엔티티에 매핑되는 테이블의 해당 컬럼은 숫자타입으로 바뀌지 않고 문자열 타입으로 유지된다.
validate
validate
는 다른 속성들과는 다르게 DDL을 작성하여 테이블을 생성하거나 수정하지 않고, 엔티티 클래스와 테이블이 정상적으로 매핑되는지만 검사한다. 만약 테이블이 아예 존재하지 않거나, 테이블에 엔티티의 필드에 매핑되는 컬럼이 존재하지 않으면 예외를 발생시키면서 애플리케이션을 종료한다.
이 경우도 update
와 비슷하게 엔티티 클래스의 필드가 매핑되는 테이블에 모두 존재하기만 한다면, 테이블의 컬럼이 더 많더라도 아무 일도 일어나지 않는다.
none
(default)
none
은 사실 속성이 존재하는 것이 아니라 위의 4가지 경우를 제외한 모든 경우에 해당한다.(다만 스프링부트의 경우에는 none
이라고 명시하거나 아예 ddl-auto
속성을 명시하지 않아야 한다.) 이 경우에는 아무 일도 일어나지 않는다.
ddl-auto
속성을 사용할 때 주의사항
이상의 ddl-auto
속성들은 얼핏 보기엔 굉장히 편리해보이지만 validate
와 none
을 제외한 속성은 운영 DB에는 절대!!! 사용하면 안된다. update
라면 그나마 낫지만, create
나 create-drop
으로 설정한 채로 운영 DB에 연결하여 애플리케이션을 실행해버리면 운영 DB의 테이블이 몽땅 삭제되는 대참사가 일어나게 된다.
update
라고 하더라도 문제가 될 수 있는 것이, 만약 update
로 인해 새로 추가된 컬럼이 not null이라면 해당 변경사항이 반영되지 않은 버전을 배포하게 되었을 때 테이블에 데이터가 INSERT 되지 않을 수 있다.
따라서, 영한님의 JPA 강의에서는 아래와 같이 이 속성을 주의해서 사용할 것을 강조하고 있다. 또한 DDL을 날리는 것은 JPA에서 자동으로 작성해 주더라도 결국엔 사람의 손을 거쳐야 한다고 한다.
- 개발 초기 단계 또는 로컬에서 테스트 :
create
또는update
- 테스트 서버 :
update
또는validate
- 스테이징 및 운영 서버 :
validate
또는none
스프링부트 프로젝트에서 다중 프로파일 사용 시 추가 주의사항
다중 프로파일을 사용하여 스프링부트 프로젝트의 속성을 관리하고 있다면 운영 프로파일의 ddl-auto
속성은 반드시 validate
나 none
으로 명시하거나, 공통 속성에 작성하지 않고 각 프로파일의 속성에 작성해야한다. [Spring Boot] 다중 Profile을 이용하여 환경에 따라 다른 설정 적용하기에서 언급했듯이 다중 프로파일을 사용하게 되면 해당 프로파일에 설정하지 않은 속성은 공통 속성에서 가져오게 된다.
위 영상의 뒷부분에도 나와있지만, 사건이 터진 원인이 공통 속성에 ddl-auto
를 create
로 설정했는데 운영용 프로파일에서는 설정을 해놓지 않았기 때문에 공통 속성의 create
를 가져와서 발생한 것이라고 한다.
결론
ddl-auto
속성은 테스트 환경에서는 분명히 편리한 기능이 맞지만 운영 서버에서는 최소한의 검증만을 위해서 사용하거나, 아예 사용하지 않아야 한다. 호돌맨님의 사례도 매일 DB를 백업하고 있었기에 금방 복구할 수 있었던 것이고, DB를 백업하지 않거나 백업 주기가 길었다면 굉장한 참사가 발생했을지도 모를 일이라고 생각한다.
'Development > JPA' 카테고리의 다른 글
[Spring Data JPA] Java의 record 객체를 @EmbeddedId로 사용할 때 Could not set value of type 문제가 발생하는 경우 (0) | 2024.08.02 |
---|---|
[JPA] 트랜잭션의 전파와 UnexpectedRollbackException 이슈 (0) | 2024.01.29 |
[JPA] Service 계층에서 DataIntegrityViolationException을 처리하기 (2) | 2023.04.25 |
[Kotlin/JPA] 코틀린과 JPA를 함께 사용할 때 추가적으로 설정해야 하는 것들과 Data class (0) | 2023.03.29 |
[JPA] 양방향 연관 관계에서 연관 관계의 주인 설정과 주의 사항 (0) | 2023.03.22 |
댓글