1️⃣ @DynamicInsert와 @DynamicUpdate가 무엇인지 ?

JPA의 구현체인 하이버네이트(Hibernate)에서 제공하는 어노테이션이다.

엔티티의 INSERT 및 UPDATE 쿼리를 생성하는 방식을 최적화하기 위해 사용된다.

하이버네이트가 INSERT 또는 UPDATE 쿼리를 고정된 형태가 아닌,

실제 엔티티의 상태에 따라 동적으로 생성하도록 하여 성능상 이점을 얻기 위해 사용하는 어노테이션 !

 

2️⃣ @DynamicInsert와 @DynamicUpdate가 어떻게 작동되는 지 ?

기존 방식

  1. JPA (정확히는 하이버네이트와 같은 JPA 구현체)는 기본적으로 엔티티의 영속성 상태 변화를 감지하여 자동으로 SQL 쿼리를 생성하고 실행한다.이 방식은 쿼리 생성 로직이 단순하다는 장점이 있지만, 불필요하게 많은 컬럼을 포함시키는 단점이 있다.
  2. 예시 
    1. INSERT: 기본적으로 모든 컬럼을 INSERT 문에 포함시킴
    2. UPDATE: 업데이트 가능한 모든 컬럼을 UPDATE 문의 SET 절에 포함시킴.

 

@DynamicInsert, @DynamicUpdate 적용

  1. 1. 엔티티 클래스 레벨에 @DynamicInsert 를 붙이면 적용된다.
  2. 예시
    1. INSERT: null이 아닌 필드들만 INSERT 문에 포함시킴
    2. UPDATE: 엔티티가 컨텍스트에 로딩된 후 실제로 값이 변경된 필드들만 SET절에 포함시킴

 

 

3️⃣ 적용 시 장단점

구분 기존 @DynamicInsert/Update
장점 쿼리 생성 로직이 단순하여 하이버네이트 내부 처리 부하가 적음 - 쿼리 문자열이 짧아지기 때문에 네트워크 부하가 줄어듦
- 불필요한 컬럼의 삽입/갱신을 막아 데이터베이스 부하를 줄일 수 있음
- null 값 삽입시 DB의 DEFAULT값이 적용되도록 유도할 수 있음.
- 실제 변경된 컬럼만 갱신하여 동시성 충돌 가능성을 줄일 수 있음
단점 - 불필요하게 많은 컬럼을 쿼리에 포함시켜 쿼리 문자열이 길어지고 네트워크 부하가 증가할 수 있음
- 데이터베이스의 DEFAULT 값이 아닌 명시적인 NULL이 삽입될 수 있음 (@DynamicInsert 시 기대하는 동작과 다를 수 있음)
- 값이 변경되지 않은 컬럼도 다시 갱신하여 불필요한 쓰기 작업이 발생할 수 있음.
어떤 컬럼을 쿼리에 포함시킬지 결정하는 추가적인 내부처리가 필요하여 하이버네이트 내부 처리 부하가 소폭 증가할 수 있음

 

 

4️⃣ 언제 적용하면 좋을까 ?

  • 엔티티의 컬럼 수가 매우 많은 경우
    • 컬럼 수가 많을 수록 불필요하게 포함되는 컬럼이 많아져 쿼리 문자열이 길어지고 네트워크 및 데이터베이스 부하가 커진다.
  • INSERT 시 대부분의 컬럼이 null이거나 DB의 DEFAULT 값을 사용하고 싶은 경우
    • @DynamicInsert → 명시적으로 null을 삽입하는 대신 DB의 기본값을 사용하도록 유도
  • UPDATE 시 변경되는 컬럼의 수가 적은 경우
    • 전체 컬럼 중 실제로 몇 개만 변경되는 경우가 빈번하다면, 변경된 컬럼만 갱신함으로써 데이터베이스 쓰기 부하를 줄이고 쿼리 크기를 최적화할 수 있음.
  • 성능 최적화가 필요한 와이드(Wide) 테이블 (컬럼이 많은 테이블): 대규모 데이터 처리에서 쿼리 크기나 불필요한 쓰기 작업이 병목이 될 수 있다면 고려해볼 수 있음.

🚨 주의사항

  • @DynamicInsert와 @DynamicUpdate는 하이버네이트의 확장 기능이며 표준 JPA 기능은 아니다.
  • 성능 측정 없이는 명확한 효과를 단정하기 어려움. 때로는 기본 동작이 더 나은 성능을 보이기도 함.
  • 단순히 컬럼 수가 적고 변경이 잦은 테이블에는 큰 이점이 없을 수 있으며, 오히려 내부 처리 부하 때문에 미미하게나마 성능 저하가 있을 수 있음.

+ Recent posts