주니어 개발자들이 읽으면 좋은 테크 아티클 모음
F-Lab : 상위 1% 개발자들의 멘토링
JPA의 더티 체킹은 어떻게 수행할까요?
최근 제가 유지보수하고 있는 서비스에서 조회 한 번에 43건의 업데이트 쿼리가 발생하는 것을 확인했습니다. 로컬 환경에서 동일하게 재현해보니, 해당 로직은 조회성 로직인데도 불구하고 업데이트 쿼리가 무분별하게 발생하고 있었습니다.
해당 로직에는 명시적으로 업데이트하는 부분이 보이지 않아, 이는 트랜잭션 내에서 JPA 더티 체킹이 작용하고 있다고 짐작했습니다.
조회성 로직이기 때문에 트랜잭션에 readOnly
옵션을 적용하면 해결될 수 있지만, 43건의 쿼리를 발생시킨 근본적인 원인을 파악해보기로 했습니다.
먼저, 로컬 환경에서 Hibernate가 기본적으로 찍는 쿼리 로그만으로는 파악이 어려워서 @DynamicUpdate
를 사용하여 업데이트 쿼리를 발생시키는 필드를 찾아내고자 했습니다. 의도한 대로 특정 필드만 업데이트 쿼리에 포함되어 나갔는데, 해당 필드는 @Convert
가 사용된 필드였고 특정 클래스(편의상 UserName 클래스)가 사용되고 있었습니다.
그럼 왜 JPA는 더티 체킹을 하고 있었을까요? 이유는 UserName 클래스에 equals가 재정의되지 않았기 때문이었습니다. JPA가 스냅샷을 보관하고 트랜잭션이 커밋될 때 Entity(편의상 User) 객체의 동등성 비교를 수행하는데, 이때 UserName의 equals가 재정의되어 있지 않아서 해당 필드의 userName을 매번 다른 객체로 인식한 것이었습니다.
이번 경험을 통해 다시 한번 느낀 점은 동등성 비교를 위해 equals를 잘 정의하는 것이 중요하다는 것입니다! equals 재정의 없이 map의 key로 사용하는 코드를 꽤 많이 봤습니다. (Java record는 예외이지만)
아무튼 꽤나 재밌는 이슈였습니다. 읽어주셔서 감사합니다.
다음 내용이 궁금하다면?
이미 회원이신가요?
2024년 3월 20일 오전 8:25
고용노동부가 주관하는 청년미래플러스 사업, 이전에 공유했었는데요.
... 더 보기솔
... 더 보기이
... 더 보기주
... 더 보기