@Transactional(readOnly = true)에서 readOnly = true는 무슨 역할이고 꼭 써야할까?

주리링·2022년 5월 16일
2

우테코 생존기

목록 보기
8/17
post-thumbnail

Transaction

하나의 flow로 처리해야하는 로직으로 데이터베이스의 상태를 바꾸기 위해 더 이상 쪼개질 수 없는 최소의 연산을 의미합니다.

ACID

transaction은 ACID의 특성을 가집니다.

원자성(Atomicity)

트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 특성

일관성(Consistency)

트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 특성

독립성(Isolation)

트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 특성

지속성(Durability)

성공적으로 수행된 트랜잭션은 영원히 반영되어야 함을 의미하는 특징
스템 문제, DB 일관성 체크 등을 하더라도 유지되어야 함을 의미합니다.

@Transactional

Transactional 어노테이션은 해당 어노테이션이 붙은 메서드가 transaction이 되도록 보장해주는 Spring AOP 기반의 어노테이션입니다.

예를 들어, 사용자가 배달 상품을 주문하면 상점에서는 주문이 접수되어야 합니다.
또한 라이더도 배정되어야 합니다.
만약 배달 상품을 주문하는데는 문제가 없지만 상점에 주문이 접수될 때 문제가 생긴다면 주문된 배달 상품은 어떻게 해야할까요?

이런 문제에서 @Transactional을 사용하면 해당 메서드를 실행하기 전의 db 상태로 되돌릴 수 있습니다.

@Transactional(readOnly = true)

@Transactional 작업을 처리하기 위해 많은 리소스가 사용됩니다.
특히 CUD sql문에서는 이전 상태로 돌려야하기 때문에, 이전 상태를 가지고 있어야합니다.
하지만 select문 같은 경우는 쿼리를 실행해도 이전 상태와 변화가 없으므로 해당 transaction에 lock을 적용할 필요가 없습니다.

그렇기때문에 (readOnly = true) 옵션을 사용하여 해당 메서드가 읽기 전용이라는 것을 명시하고, 영속성 컨텍스트에 관리를 받지않게 됩니다.
또한 변경감지 수행등을 하지 않아 @Transactional의 격리 수준보다 낮은 수준의 격리 수준을 사용하게 됩니다.

여기까지 알고 난 후, 의문이 하나 들었습니다.

그렇다면 JPA를 쓰지 않는다면 굳이 왜 @Transactional(readOnly = true)를 사용할까? 그냥 transaction 어노테이션을 사용하지 않아도 되지 않나?

그래서 @Transactional(readOnly = true) 사용했을 때의 장단점을 살펴보려고 합니다.

장점

  • readOnly라고 명시하므로 읽는 개발자가 읽기 전용 메서드라는 것을 알 수 있습니다.
  • JPA를 사용할 경우, 변경감지 작업을 수행하지 않아 성능상의 이점이 있습니다.
  • 트랜잭션 ID 설정에 대한 오버헤드를 해결하고, 스냅샷을 통해 데이터의 일관성을 보장한다.
  • CRUD를 하는 service에서 클래스에 @Transactional을 붙여 중복을 줄이고 싶을 때 read 메서드에 사용하여 격리 수준을 바꿔줄 수 있다.

단점

  • 사용하지 않았을 때보다 자원(프록시)을 사용하므로 느리다.
    참고

좁은 견해로 장단점은 이정도로 정리할 수 있을 것 같습니다.

JPA를 쓰지 않을 때는 사실 성능상으로 큰 이점이 없어보여서 (read 명시 + 클래스에 어노테이션을 붙였을 때 read 메서드 처리가능) VS 프록시 사용 중에서 해당 프로젝트의 장단점을 따져서 사용하면 될 것 같습니다.

profile
코딩하는 감자

0개의 댓글