“어이 신입, 탈출각이다” | 요즘IT
요즘IT
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
성장이 어려운 환경에서의 개발자 생활
저런 개발자 생활도 한적이 있어서 다양한 생각이 든다.
제가 한국에서 직장 생활을 시작하고 가장 먼저 배운 것은 아이러니하게도 야근이었습니다. 신입이었던 제게 야근은 선택의 문제가 아니었거든요. 선배들에게 야근은 너무나 당연한 루틴이었고, 저녁 5시가 되면 "퇴근 안 해?"가 아니라 "저녁 뭐 먹을까?"라는 질문을 던졌습니다. 누가 정해놓은 것처럼 부장님이 퇴근해야 과장님이, 과장님이 퇴근해야 대리님이, 대리님이 퇴근해야 비로서 저 같은 신입도 퇴근 생각을 할 수 있었습니다.
... 더 보기작
... 더 보기1. 유명한 경제학자 케인스는 단기 투자 전략을 미인선발대회에 비유했다.
안
... 더 보기고용노동부에서 주관하는 청년미래플러스 3기를 모집 중이라고 합니다.
구직자와 재직자 두 가지 트랙을 동시에 모집한다고 하네요.
모집 기간: 6월 15일 ~ 8월 3일