@Transactional(readOnly = true) ??

·2023년 4월 24일
2

레벨 2의 자동차 미션을 진행하던 중에 Service 레이어에서 @Transational 어노테이션을 사용했다.
어떤 메서드에 대해서 Atomic 하게 처리하기 위해서 사용했는데, 이때 영속 레이어의 읽기 작업만 호출할 때는 추가로 readOnly 옵션을 적용해줬다.

그랬더니…

클래스 스코프에 readOnly 설정을 해주고 쓰기 작업이 필요한 메서드에는 다시 @Transational을 붙여줘서 readOnly를 false로 지정해준 상태였다.

하지만 이것이 정확히 무엇을 하는 지 잘 몰라서 대답할 수가 없었다…

지금부터 알아보자.

Transaction ??

DB를 공부할 때 Transaction 이란 개념이 나온다. 이것은 다음과 같은 네가지의 성질을 가진다.

  • 원자성(Atomicity)
    • 한 트랜잭션 내에서 실행한 작업들은 하나로 간주한다. 모두 성공 또는 모두 실패
  • 일관성(Consistency)
    • 트랜잭션은 일관성 있는 데이타베이스 상태를 유지한다.
  • 격리성(Isolation)
    • 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리해야한다.
  • 지속성(Durability)
    • 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 한다.

동시적인 접근이 가능한 상황에서 의도치 않은 상황 발생을 막기 위해 사용한다.
스프링에서는 선언적 트랜잭션을 지원하는데, 이것이 바로 @Transactional 어노테이션이다.

스프링에서의 @Transactional

클래스, 메서드 단위로 해당 어노테이션을 붙일 수 있다.
클래스 단위로 붙인다면, 해당 클래스의 모든 메서드에 디폴트 설정으로 적용이 된다.
메서드 단위로 붙이면 클래스 단위 적용을 덮어씌울 수 있다.

해당 클래스 또는 메서드에 트랜잭션 기능이 적용된 프록시 객체가 생성되고 사용하게 된다.
PlatformTransactionManager를 사용해서 Commit(성공) 또는 Rollback(실패) 한다.

사실 단순히 어노테이션만으로 완벽한 상황을 보장해주는 것은 아니다.
다수의 Transaction이 동시에 같은 리소스에 접근 하는 경우 Dirty Read, Non-Repeatable Read, Phantom Read 등의 문제가 발생할 수 있다.
이를 위해서 @Transactional 어노테이션에서는 여러가지 옵션을 사용할 수 있는데 이번 글의 주제인 readOnly에 대해 집중해보려고 한다.

@Transactional(readOnly = true)

우선 문자열 그대로 해당 트랜잭션은 읽기 작업만 하도록 적용하는 것이다.
이를 통해서 얻을 수 있는 이점은 다음과 같다.

  • 성능 최적화
  • 쓰기 작업이 일어나는 것을 의도적으로 방지

만약 프로젝트에서 JPA를 쓴다면 변경 감지 기능에 의해서 flush가 일어나게 된다. 이 기능을 위해서 각 시점의 스냅샷 인스턴스를 메모리에 보관하고, flush 때 스냅샷 비교 등의 무거운 작업을 수행한다.
이때 readOnly = true 상태라면 강제로 플러시를 호출하지 않는 한 플러시가 일어나지 않는다.
또한 스프링 5.1부터는 스냅샷을 저장하지 않아서 메모리 또한 아낄 수 있다.

사실 이 readOnly 설정은 힌트 옵션이다. @Transactional.java를 들어가보면 다음과 같이 쓰여있다.

위의 JPA 내용이 주요 기능은 아니고 트랜잭션을 수행하는 하위 시스템(DB, API 등)에게 힌트를 제공하는 것이다. 만약 DB에서 읽기 Lock과 쓰기 Lock을 따로 관리하는 경우, 의도치 않은 쓰기 작업을 막아주는 등의 역할을 할 수 있다.

하지만…!! 하위 시스템에게 동작을 맡기기 때문에 해당 옵션을 설정했다고 해서 모든 환경에서 쓰기 작업이 실패한다고 보장할 수도 없다.

그럼에도 불구하고 읽기 작업일 경우 해당 옵션을 적용하는 것이 더 좋기 때문에 적용하는 것이다!!

추가 정보

  • private 메서드에는 @Transactional이 적용되지 않는다
    • 프록시 객체에서 해당 메서드에 접근할 수 없기 때문
    • 해당 어노테이션이 있어도 무시
profile
渽晛

0개의 댓글