🍎 Backend/Spring

[스프링부트] @Transational(readOnly=true)에 대해서

밈98 2023. 7. 21. 11:13

 

@Transational

  • 메서드 내 작업을 마칠 경우 자동으로 flush() 메서드 실행
  • 변경이 감지 될 시, 대상 객체에 해당하는 데이터베이스의 레코드를 업데이트 하는 쿼리 실행
  • 모든 예외 및 에러에 대해 롤백 처리하지 않음!
  • Runtime Exception 또는 Error시에만 롤백
    • Runtime Exception
      개발자가 처리하기 어려운 예외로 말 그대로 프로그램 실행 중에 발생하는 예외를 의미
    • Checked Exception
      프로그램이 제어할 수 없지만 개발자가 충분히 처리 가능한 예외
    • Error
      Exception이 아닌 경우로 시스템 메모리 부족처럼 예측 및 처리가 어려움
  • 동일한 코드이다
@Transactional 
@Transactional(rollbackFro = {RuntimeException.class, Exception.class})

 

@Transactional(readonly=True)

  • 읽기 전용 모드
  • 예상치 못한 엔티티의 등록,변경,삭제를 예방할 수 있고, 성능을 최적화 할 수 있다

읽기 전용 쿼리의 성능 최적화

엔티티가 영속성 컨텍스트에 관리되면 1차 캐시부터 변경 감지까지 얻을 수 있는 혜택이 많지만,
변경감지를 위해 스냅샷 인스턴스를 보관하므로 더 많은 메모리를 사용하는 단점이 존재함

만일 조회만 하는 경우에 전용으로 엔티티를 조회하면 메모리 사용량을 최적화 할 수 있음.

readOnly=true 옵션을 줄 경우, 스프링 프레임워크가 하이버네이트 세션 플러시 모드를 MANUAL로 설정한다. 강제로 플러시를 호출하지 않는 한 플러시가 일어나지 않는다.

이후 트랜잭션을 commit하더라도 영속성 컨텍스트가 플러시 되지 않아 등록,수정,삭제 동작X
읽기 전용으로, 영속성 컨텍스트는 변경감지를 위한 스탭샷을 보관하지 않으므로 성능이 향상된다.

 

안사용하면 되지 않을까??에 대한 궁금증

jpa를 사용하면서, 이미 정의된 메서드를 설정없이 사용하면?!

  • save, delete, update 대해 @Transaction 이 자동으로 사용되고 있다(readOnly = false)
  • select문인 find에 대해선 @Transaction(ReadOnly = true) 옵션이 사용된다.

 

  1. 객체지향으로 작업이 가능한 경우에 final을 두어서 객체의 신뢰성을 보장하는 것이 좋다
  2. 의도치 않게 데이터가 변경되는 일을 사전에 방지 할 수 있다.
  3. MySQL을 사용할 때 데이터가 날아가는 것을 방지하기 위해서 이중화 구성(master - Slave)을 하는 경우가 있음
    • DB가 master와 slave로 나누어져 있다면 readOnly = true로 있는 경우에는 읽기 전용으로 master가 아닌 slave를 호출함
    • 즉, 상황에 따라 DB 서버의 부하를 줄이고 약간의 최적화를 할 수 있다.
  4. @Transactional(readOnly=true) 어노테이션이 있다면 코드를 접하는 사람들이 직관적으로 보기에 해당 메서드는 READ에 대한 동작만 수행할 것이라고 예상함.
    • 이 어노테이션을 보고 누구나 한눈에 알아볼 수 있고, 신뢰성을 보장한다고 받아들일 수 있다.

 

정리


아무런 성능적 이점을 갖지 못하는 경우에도 명시적으로 두고 사용하는 것이 좋다.



참고) https://resilient-923.tistory.com/391