Cause of Death: Spring Data JPA by Thorben Janssen @ Spring I/O 2025
- Spring Data JPA 프로젝트에서 흔히 발생하는 실수와 안티패턴을 통해 성능 저하, 데이터 불일치, 데이터 손실을 유발하는 방법을 역설적으로 설명하고 올바른 해결책을 제시합니다. 😈
LazyInitializationException은 트랜잭션 컨텍스트 외부에서 지연 로딩된 관계에 접근할 때 발생하며, FetchType.EAGER로 변경하는 것은 종종 N+1 문제를 야기하는 잘못된 해결책입니다. 💥
- N+1 Select 문제는
FetchType.EAGER 사용 또는 지연 로딩된 컬렉션을 반복할 때 각 항목에 대해 추가 쿼리가 발생하여 심각한 성능 저하를 초래합니다. 🐢
- N+1 문제 및
LazyInitializationException의 올바른 해결책은 JPQL/HQL 쿼리에서 JOIN FETCH를 사용하여 필요한 관계를 단일 쿼리로 명시적으로 가져오는 것입니다. 🚀
- 개발 환경에서
hibernate.generate_statistics를 활성화하여 JDBC 통계를 모니터링하면 쿼리 성능 문제를 식별하는 데 매우 유용합니다. 📊
- Many-to-many 관계를
List (Hibernate의 'bag')로 모델링하면, 단일 레코드 변경 시에도 모든 관계를 삭제하고 다시 삽입하는 비효율적인 업데이트가 발생할 수 있습니다. 🗑️
- Many-to-many 관계에는
List 대신 Set을 사용하여 Hibernate가 관계를 훨씬 효율적으로 관리하고 불필요한 중복을 방지하도록 해야 합니다. ✅
- 여러 개의
List 기반(bag) to-many 관계를 동시에 JOIN FETCH하려고 하면 MultipleBagFetchException이 발생합니다. 🚫
- JPA의 2차 캐시는 사용자 정의 쿼리에는 적용되지 않고, ID를 통한 엔티티 조회에만 사용되므로, 대부분의 쿼리 기반 사용 사례에서는 성능 이점을 얻기 어렵습니다. 🧠
- 사용자 정의 쿼리의 결과를 캐싱하기 위해 Hibernate의 쿼리 캐시를 활성화하는 것이 대안이 될 수 있습니다. 💡
데브허브 | DEVHUB | Cause of Death: Spring Data JPA by Thorben Janssen @ Spring I/O 2025