본문 바로가기
회고록/Project

[42GG] JPA UPDATE 로직 (영속성 컨텍스트, @DynamicUpdate, 벌크 연산)

by yhames 2024. 7. 17.
728x90

42GG 프로젝트

프로젝트를 진행하면서 엔티티를 업데이트하는 기능을 맡아서 구현하고 있다.
 
업데이트 관련된 로직에서 JPA는 더티체킹을 통해 엔티티 변경을 감지한다.
그리고 보통 엔티티는 setter를 구현하지 않고 명확한 의도를 가진 메서드를 구현한다.
 
하지만 엔티티에 필드가 많아지게 된다면 setter를 대신하는 메서드를 모든 필드에 대해서 구현해야하는 불편함이 있다.
 
이를 해결하기 위해서 여러가지 방법을 생각해보다가
이번에 승수님과 함께 해당 부분에 대해서 심도 깊은 논의를 진행했다.
 
먼저 JPA에서 업데이트를 수행하는 로직은 다음과 같이 3가지가 있다.
 

  1. JPA 영속성 컨텍스트더티체킹을 사용해서 업데이트한다.
  2. @DynamicUdpate를 사용해서 특정 컬럼만 업데이트한다.
  3. JdbcTemplate이나 Spring Data JPA의 @Query를 활용하여 벌크연산을 한다.

 
먼저 나와 승수님은 영속성 컨텍스트와 더티체킹을 하면 특정 필드 대해서만 UPDATE 쿼리가 나간다고 생각을 했었다.
하지만 실제로는 모든 필드가 같이 쿼리로 나가고 있었고, 특정 필드에 대해서만 쿼리를 보내기 위해서는 @DynamicUdpate를 사용해야한다.
 
아직 내부 동작까지 확인하지는 않았지만 @DynamicUdpate를 사용하면 특정 필드 대해서만 쿼리를 보내지만, 영속성 컨텍스트에서 캐싱된 쿼리를 사용하지 않고 동적쿼리를 생성하기 때문에 성능면에서 트레이드 오프가 있다고 한다.
따라서 @DynamicUdpate를 통해 성능 향상을 하려면 필드가 30개 정도로 지나치게 많거나, 특정 필드의 크기가 너무 크고 수정이 빈번하지 않다면, @DynamicUdpate을 고려하면 좋을 것 같다는 결론을 내렸다.
 
추가적으로 벌크 연산에 대해서도 알아보았다.
만약 다수의 엔티티를 벌크로 업데이트해야한다면, 즉 UPDATE 쿼리가 여러개 나가야한다면 JdbcTemplate이나 Spring Data JPA의 @Query를 활용하여 한방쿼리로 해결한다는 것이다. 무조건 영속성 컨텍스트과 더티체킹을 사용해서 업데이트를 해야한다는 고정관념을 가지고 있었는데, 다시 한 번 많이 배우게 된 것 같다.
 
결과적으로 현재 업데이트 기능에서는 더티체킹을 통해 변경을 감지하는 방식을 유지하기로 결정했다. 엔티티의 필드가 15개 여서 엔티티에 메서드가 늘어났지만, @DynamicUdpate를 사용하기에는 성능면에서 이점이 없다고 생각을 했다.
물론 이후에 추가적인 검증이 필요하겠지만, 먼저 기능 구현이 완료되면 진행해 볼 예정이다.
 

반응형