더티 체킹 (Dirty Checking)
기술노트
[Spring Data JPA] 더티 체킹 (Dirty Checking)
트랜잭션 안에서 Entity의 변경이 일어났을 때 변경한 내용을 자동으로 DB에 반영하는 것을 "더티 체킹(Dirty Checking)"이라고 한다.
ORM 구현체나 JPA를 사용할 때 자주 언급되는 이 기능은 변경 감지(change detection)를 기반으로 한다.
예시: 주문 취소 기능
@Transactional
public void cancelOrder(Long orderId) {
// 주문 엔티티 조회
Order order = orderRepository.findOne(orderId);
// 주문 취소
order.cancel();
}
위 코드는 주문 ID로 주문을 조회하고, 주문을 취소하는 메소드이다.
update
쿼리를 명시적으로 작성하지 않았음에도 불구하고, 데이터베이스에는 변경된 상태가 반영된다.
이는 다음과 같은 흐름으로 동작한다:
- 트랜잭션 시작
- Entity 조회
- Entity 내부 상태 변경
- 트랜잭션 커밋 시점에 변경 사항 감지 및 자동 update
이 모든 흐름을 가능케 하는 것이 바로 더티 체킹이다.
더티 체킹 작동 방식
더티 체킹은 JPA가 트랜잭션 커밋 직전에 수행하는 다음 절차로 작동한다:
- Entity 조회 시점에 스냅샷(snapshot) 생성
- 트랜잭션 커밋 시 현재 상태와 스냅샷 비교
- 변경이 감지되면 update 쿼리 생성 및 전송
Dirty : 상태의 변화가 생김
Checking : 검사
즉, 변경된 필드를 자동으로 감지하여, update 쿼리를 생성해주는 기능이다.
대상
더티 체킹은 "영속성 컨텍스트"가 관리하는 Entity에만 적용된다. 준영속(detached) 혹은 비영속(transient) 상태의 객체는 변경을 감지하지 못하므로, 데이터베이스에도 반영되지 않는다.
성능 고려: @DynamicUpdate
기본적으로 JPA는 Entity의 모든 필드를 대상으로 update 쿼리를 생성한다. 필드 수가 많을 경우 이는 성능에 비효율적일 수 있다.
이때 @DynamicUpdate
애노테이션을 사용하면 실제 변경된 필드만 update 쿼리로 반영되도록 설정할 수 있다.
@Getter
@NoArgsConstructor
@Entity
@DynamicUpdate
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String product;
// 기타 필드
}
요약
- 더티 체킹은 JPA가 영속성 컨텍스트 안에서 Entity의 변경을 감지하고 DB에 자동 반영하는 기능이다.
- 명시적 쿼리 작성 없이도 update가 가능하다.
- 트랜잭션 커밋 시점에만 반영된다.
@DynamicUpdate
를 통해 성능 최적화 가능하다.