카테고리 없음

[Spring boot] Service class에 @Transactional(readOnly = true)를 붙인 이유

ckm7907 2024. 8. 10. 20:27

Service단에 @Transactional(readOnly = true)

프로젝트를 진행하며 Transactional(readOnly = true)를 굳이 왜 붙이는 지 궁금해서 찾아 보았다.

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class RoomService {

일반적으로, 조회용 메서드에 대해서는 readOnly를 설정함으로써 성능상 이점을 얻을 수 있다.

JPA - DirtyChecking와의 연관

트랜잭션이 Commit 될 때, 초기 상태의 정보를 가지는 Snapshot 과 Entity의 상태를 비교하여 변경된 내용에 대해 update query를 생성해 쓰기 지연 저장소에 저장한다.

그 후, 일괄적으로 쓰기 지연 저장소에 저장되어 있는 SQL query를 flush 하고 데이터베이스의 트랜잭션을 Commit함으로써 우리가 update와 같은 메서드를 사용하지 않고도 Entity의 수정이 이루어 진다.

이를 Dirty Checking 이라 한다.

 

이 때, readOnly로 설정하면 스프링 프레임워크는 JPA의 세션 플러시 모드는 MANUAL으로 설정한다.

(트랜잭션내에서 사용자가 수동으로 flush를 호출하지 않으면 flush가 자동으로 수행되지 않는 모드)

1. 조회용으로 가져온 Entity의 예상치 못한 수정을 방지

2. 트랜잭션 내에서 조회하는 Entity는 조회용임을 인식하고 변경 감지를 위한 Snapshat을 따로 보관하지 않아 메모리가 절약되는 성능상 이점

 

조회용 메서드에 그냥 @Transactional 어노테이션을 안 붙이면 되지 않나?

조회용 메서드에 대해 @Transactional 어노테이션 유무의 차이는 OSIV(Open Session In View)가 꺼져 있을 때 알 수 있다.

OSIV는 영속성 컨텍스트를 View Layer까지 유지하는 속성으로, 클라이언트의 요청 시점부터 영속성 컨텍스트를 생성하여 Filter / Interceptor - Controller에서 부터 영속성 컨텍스트가 생성되어 유지됨으로써 View Layer에서도 Entity의 Lazy Loading이 가능하도록 한다.

 

기본적으로 별도의 설정을 하지 않는다면 OSIV는 true로 설정되어 있어 @Transactional 어노테이션 유무의 차이를 알 수 없다.

 

### 출처

https://hungseong.tistory.com/74