@Transactional(readOnly=true)에 대하여

na.ram·2024년 8월 27일

Spring

목록 보기
3/13
post-thumbnail

@Transactional(readOnly=true)의 이점

원래 @Transactional 어노테이션을 선언하게 되면 변경 감지(Dirty Checking)가 이루어지게 되지만 readOnly = true로 설정하면 스프링 프레임워크는 JPA의 세션 플러시 모드를 MANUAL로 설정한다.

그로 인해 해당 어노테이션 영역 내에서는 트랜잭션 내에서 강제로 flush()를 호출하지 않는 한 수정 내역이 DB에 적용되지 않으며, 조회용으로 가져온 Entity의 예상치 못한 수정을 방지할 수 있다.

또한, readOnly = true를 설정하면 JPA는 해당 트랜잭션 내에 조회하는 Entity가 조회용임을 인식하고, 변경 감지를 위한 Snapshot을 따로 보관하지 않으므로 메모리가 절약되는 성능상 이점 역시 존재한다.


그런데 애초에 조회 메서드에 @Transational 어노테이션을 달지 않으면 어떨까?

@Transactional 어노테이션을 선언하지 않는 것과는 어떤 차이가 있을까?

이 부분을 알기 위해서는 먼저 OSIV를 알아야 한다.

OSIV

OSIV(Open Session In View)는 영속성 컨텍스트를 뷰까지 유지하는 기능이다. 본래 영속성 컨텍스트는 트랜잭션 생명 주기와 동일하지만 이 옵션이 true로 설정되어 있다면 영속성 컨텍스트의 생명주기를 View까지 유지시켜 Entitiy의 Lazy Loading이 가능하도록 한다. ( OSIV 옵션은 기본이 true이다. )

사실 OSIV 옵션이 true로 설정되어 있으면 @Transactional 어노테이션 유무의 차이를 알 수가 없다.


그러나 OSIV 옵션이 false로 설정된다면 영속성 컨텍스트는 트랜잭션의 생명주기와 동일하기 때문에 Entitiy는 영속성 컨텍스트의 관리를 받지 않는 준영속 상태가 되어버린다.

영속성 컨텍스트가 준영속 상태가 된다는 말은 곧, Lazy Loading의 동작이 불가능하다는 의미이다.

해당 상태에서 Lazy Loading을 사용하게 되면 LazyInitializationException이 발생하기 때문에 조회용 메서드라고 하더라도 @Transactional 어노테이션을 붙여주어야 한다.

OSIV 옵션별 장/단점

spring.jpa.open-in-view: true

  • 장점 - 지연 로딩을 사용할 때 트랜잭션의 범위를 고려하지 않고 간편하게 코드 작성 가능
  • 단점 - API의 응답이 끝날 때까지 DB 커넥션을 오래 유지하게 되며 실시간 트래픽이 중요한 서비스의 경우에는 커넥션 문제로 인한 시스템 장애로 이어질 수 있음

spring.jpa.open-in-view: false

  • 장점 : DB 커넥션의 낭비가 없음
  • 단점 : 지연 로딩을 트랜잭션 내에서 처리하고 반환해주거나 fetch join을 사용해 해결하는 등과 같이 주의를 기울여야 함

정리

@Transactional(readOnly=true) 어노테이션을 선언하면 Entity의 수정 방지와 변경 감지를 위한 Snapshot을 따로 저장하지 않아 메모리적인 이점이 있다.
만약 OSIV 옵션이 true라면 해당 어노테이션을 사용하지 않아도 상관이 없지만 만약 옵션이 false라면 Exception이 발생할 수 있기 때문에 사용해야 한다.

0개의 댓글