JPA 자체 성능 최적화
JPA는 개발 생산성이 높지만 내부 동작을 이해하지 못하면 성능 문제를 일으키기 쉽다.
이 글에서는 Spring Boot + JPA 환경에서 실무적으로 자주 활용되는 JPA 자체 성능 최적화 전략들을 정리한다.
#영속성 컨텍스트(Persistence Context) 이해하기
영속성 컨텍스트는 JPA의 핵심이며 성능 최적화와 직접 관련된다.
영속성 컨텍스트가 수행하는 기능은 다음과 같다.
- 1차 캐시 관리
- 동일성 보장
- 변경 감지(Dirty Checking)
- flush 시점 관리
문제가 생기는 이유
조회한 모든 엔티티가 캐시에 보관되며, 변경 감지를 위해 스냅샷이 유지되기 때문이다.
대량 조회 시 메모리를 크게 소모하고 flush 시점마다 모든 엔티티를 비교하게 된다.
최적화 전략
- 단순 조회는 DTO로 조회
- 읽기 전용은
@Transactional(readOnly = true)적용 - 대량 처리 시 batch flush + clear 적용
for (int i = 0; i < items.size(); i++) {
process(items.get(i));
if (i % 50 == 0) {
em.flush();
em.clear();
}
}
#Batch Size로 N+1 완화하기
N+1을 Fetch Join으로 해결하기 어렵거나 페이징이 필요한 상황에서는 Batch Size가 가장 효과적이다.
Batch Size 동작 방식
연관된 엔티티를 모아서 IN 쿼리로 조회한다.
예: 100개 조회 → BatchSize 50 → 2번의 IN 쿼리로 해결
설정 방법
application.yml
spring:
jpa:
properties:
hibernate.default_batch_fetch_size: 100
엔티티 개별 설정
@BatchSize(size = 50)
@OneToMany
private List<Comment> comments;
#Dirty Checking 최소화
Dirty Checking은 JPA의 장점이지만 성능 비용이 크다.
트랜잭션 범위 내 모든 엔티티를 추적하고 flush 시점마다 비교하기 때문이다.
최적화 전략
- 조회 트랜잭션에는 `readOnly = true` 적용
- 대량 UPDATE → 벌크 쿼리 사용
- UPDATE만 필요하면 엔티티 조회 없이 바로 JPQL 사용
벌크 업데이트 예시
@Modifying
@Query("update Member m set m.status = :status where m.id in :ids")
void updateStatus(...);
#DTO 기반 조회로 select * 피하기
불필요하게 엔티티를 로딩하면 영속성 컨텍스트를 낭비하고 성능이 떨어진다.
목록/통계 조회는 DTO로 직접 조회하는 것이 정답이다.
select new com.example.MemberSummary(m.id, m.name)
from Member m
where m.active = true
장점:
- 조회 속도 향상
- 네트워크 트래픽 감소
- 1차 캐시 메모리 절약
#FlushMode 조정
기본 FlushModeType.AUTO는 SELECT 실행 전에도 flush가 발생해 성능이 느려질 수 있다.
개선 방법
em.setFlushMode(FlushModeType.COMMIT);
트랜잭션 커밋 시점에만 flush 되므로 불필요한 flush 비용이 줄어든다.
#연관관계 Fetch 전략 최적화
OneToMany를 EAGER로 두면 예상치 못한 대량 로딩이 발생해 성능이 크게 떨어진다.
기본 규칙
- 모든 연관관계 기본은 LAZY
- 필요한 경우에만 Fetch Join 또는 BatchSize 사용
마치며
JPA 자체 성능 최적화는 DB 최적화보다 난이도는 높지만 효과는 크다.
핵심 포인트는 다음과 같다.
- 영속성 컨텍스트를 이해하고 필요한 경우에만 엔티티 조회
- Batch Size로 N+1 완화
- Dirty Checking 최소화
- DTO 기반 조회로 엔티티 남용 방지
다음 글에서는 캐시(Cache) 기반 성능 최적화를 다룰 예정이다.
'TIL' 카테고리의 다른 글
| Spring Boot 성능 최적화 4 (0) | 2025.10.29 |
|---|---|
| Spring Boot 성능 최적화 3 (0) | 2025.10.28 |
| Spring Boot 성능 최적화 1 (0) | 2025.10.25 |
| 10/24 (0) | 2025.10.24 |
| 10/23 (1) | 2025.10.23 |