더티 체킹 (Dirty Checking): 두 판 사이의 차이

기술노트
(컴퓨터 과학 용어 정리 - 더티 체킹 (Dirty Checking) 추가)
 
편집 요약 없음
3번째 줄: 3번째 줄:
<br>
<br>


<img src="https://cdn.inflearn.com/public/courses/324474/course_cover/58c8632c-7a6e-4c76-9893-d7fffa32faf2/kyh_JPA_Spring2%20%E1%84%87%E1%85%A9%E1%86%A8%E1%84%89%E1%85%A1%206.png">
[[File:https://cdn.inflearn.com/public/courses/324474/course_cover/58c8632c-7a6e-4c76-9893-d7fffa32faf2/kyh_JPA_Spring2%20%E1%84%87%E1%85%A9%E1%86%A8%E1%84%89%E1%85%A1%206.png|center|600px]]


<br>
<br>


<syntaxhighlight>
트랜잭션 안에서 Entity의 변경이 일어났을 때
트랜잭션 안에서 Entity의 변경이 일어났을 때
변경한 내용을 자동으로 DB에 반영하는 것을 "더티 체킹(Dirty Checking)"이라고 한다.
변경한 내용을 자동으로 DB에 반영하는
</syntaxhighlight>
 
<br>
 
ORM 구현체 개발 시 더티 체킹이라는 말을 자주 볼 수 있다.
 
더티 체킹이 어떤 것을 뜻하는 지 간단히 살펴보자.
 
<br>


JPA로 개발하는 경우 구현한 한 가지 기능을 예로 들어보자
ORM 구현체나 JPA를 사용할 때 자주 언급되는 이 기능은 변경 감지(change detection)를 기반으로 한다.


##### ex) 주문 취소 기능
=== 예시: 주문 취소 기능 ===


<syntaxhighlight>java
<syntaxhighlight lang="java">
@Transactional   
@Transactional   
public void cancelOrder(Long orderId) {   
public void cancelOrder(Long orderId) {   
     //주문 엔티티 조회   
     // 주문 엔티티 조회   
     Order order = orderRepository.findOne(orderId);   
     Order order = orderRepository.findOne(orderId);   


     //주문 취소   
     // 주문 취소   
     order.cancel();   
     order.cancel();   
}
}
</syntaxhighlight>
</syntaxhighlight>


`orderId`를 통해 주문을 취소하는 메소드다. 데이터베이스에 반영하기 위해선, `update`와 같은 쿼리가 있어야할 것 같은데 존재하지 않는다.
위 코드는 주문 ID로 주문을 조회하고, 주문을 취소하는 메소드이다.  
<code>update</code> 쿼리를 명시적으로 작성하지 않았음에도 불구하고, 데이터베이스에는 변경된 상태가 반영된다.


하지만, 실제로 이 메소드를 실행하면 데이터베이스에 update가 잘 이루어진다.
이는 다음과 같은 흐름으로 동작한다:


* 트랜잭션 시작
* 트랜잭션 시작
* `orderId`로 주문 Entity 조회
* Entity 조회
* 해당 Entity 주문 취소 상태로 '''Update'''
* Entity 내부 상태 변경
* 트랜잭션 커밋
* 트랜잭션 커밋 시점에 변경 사항 감지 및 자동 update


이를 가능하게 하는 것이 바로 '더티 체킹(Dirty Checking)'이라고 보면 된다.
이 모든 흐름을 가능케 하는 것이 바로 더티 체킹이다.


<br>
=== 더티 체킹 작동 방식 ===


그냥 더티 체킹의 단어만 간단히 해석하면  `변경 감지`로 볼 수 있다. 좀 더 자세히 말하면, Entity에서 변경이 일어난 걸 감지한 뒤, 데이터베이스에 반영시켜준다는 의미다. (변경은 최초 조회 상태가 기준이다)
더티 체킹은 JPA가 트랜잭션 커밋 직전에 수행하는 다음 절차로 작동한다:


> Dirty : 상태의 변화가 생김
# Entity 조회 시점에 스냅샷(snapshot) 생성
>
# 트랜잭션 커밋 시 현재 상태와 스냅샷 비교
> Checking : 검사
# 변경이 감지되면 update 쿼리 생성 및 전송


JPA에서는 트랜잭션이 끝나는 시점에 변화가 있던 모든 엔티티의 객체를 데이터베이스로 알아서 반영을 시켜준다. 즉, 트랜잭션의 마지막 시점에서 다른 점을 발견했을 때 데이터베이스로 update 쿼리를 날려주는 것이다.
<syntaxhighlight lang="text">
 
Dirty : 상태의 변화가 생김
* JPA에서 Entity를 조회
Checking : 검사
* 조회된 상태의 Entity에 대한 스냅샷 생성
</syntaxhighlight>
* 트랜잭션 커밋 후 해당 스냅샷과 현재 Entity 상태의 다른 점을 체크
* 다른 점들을 update 쿼리로 데이터베이스에 전달


<br>
즉, 변경된 필드를 자동으로 감지하여, update 쿼리를 생성해주는 기능이다.


이때 더티 체킹을 검사하는 대상은 `영속성 컨텍스트`가 관리하는 Entity로만 대상으로 한다.
=== 대상 ===


준영속, 비영속 Entity는 값을 변경할 지라도 데이터베이스에 반영시키지 않는다.
더티 체킹은 "영속성 컨텍스트"가 관리하는 Entity에만 적용된다. 
준영속(detached) 혹은 비영속(transient) 상태의 객체는 변경을 감지하지 못하므로, 데이터베이스에도 반영되지 않는다.


<br>
=== 성능 고려: @DynamicUpdate ===


기본적으로 더티 체킹을 실행하면, SQL에서는 변경된 엔티티의 모든 내용을 update 쿼리로 만들어 전달하는데, 이때 필드가 많아지면 전체 필드를 update하는게 비효율적일 수도 있다.
기본적으로 JPA는 Entity의 모든 필드를 대상으로 update 쿼리를 생성한다. 
필드 수가 많을 경우 이는 성능에 비효율적일 있다.


이때는 `@DynamicUpdate`를 해당 Entity에 선언하여 변경 필드만 반영시키도록 만들어줄 수 있다.
이때 <code>@DynamicUpdate</code> 애노테이션을 사용하면 실제 변경된 필드만 update 쿼리로 반영되도록 설정할 수 있다.


<syntaxhighlight>java
<syntaxhighlight lang="java">
@Getter
@Getter
@NoArgsConstructor
@NoArgsConstructor
84번째 줄: 75번째 줄:
     private Long id;
     private Long id;
     private String product;
     private String product;
    // 기타 필드
}
</syntaxhighlight>
</syntaxhighlight>


<br>
=== 요약 ===


<br>
* 더티 체킹은 JPA가 영속성 컨텍스트 안에서 Entity의 변경을 감지하고 DB에 자동 반영하는 기능이다.
* 명시적 쿼리 작성 없이도 update가 가능하다.
* 트랜잭션 커밋 시점에만 반영된다.
* <code>@DynamicUpdate</code>를 통해 성능 최적화 가능하다.


===== [참고 자료] =====
== 참고 자료 ==


* [링크](https://velog.io/@jiny/JPA-%EB%8D%94%ED%8B%B0-%EC%B2%B4%ED%82%B9Dirty-Checking-%EC%9D%B4%EB%9E%80)
* [https://velog.io/@jiny/JPA-%EB%8D%94%ED%8B%B0-%EC%B2%B4%ED%82%B9Dirty-Checking-%EC%9D%B4%EB%9E%80 JPA 더티 체킹 정리 by jiny]
* [링크](https://jojoldu.tistory.com/415)
* [https://jojoldu.tistory.com/415 JPA Dirty Checking 개념 정리 by jojoldu]

2025년 5월 6일 (화) 04:30 판

[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가 트랜잭션 커밋 직전에 수행하는 다음 절차로 작동한다:

  1. Entity 조회 시점에 스냅샷(snapshot) 생성
  2. 트랜잭션 커밋 시 현재 상태와 스냅샷 비교
  3. 변경이 감지되면 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를 통해 성능 최적화 가능하다.

참고 자료