@Transactional - Read only 옵션을 사용해야 되는 이유

이호석·2023년 7월 5일
0

스프링 공부하던 초기시절 @Transactional(readOnly = true)를 꼭 사용해야 되나.. 사용하면 어떤 이점이 있나 하다가 MySQL 공식 문서까지 들어갔던 기억이 있다. 오늘은 이 기능을 사용하면 어떤 이점이 있는지 다루려고 한다.

어떤 메소드인지 바로 확인 가능하다.

    @Override
    @Transactional(readOnly = true)
    public GetHouseReservationRes readHouseReservationList(long memberId, long houseId)
       ...
    }

    @Transactional
    @Override
    public void updateReservationPeopleCount(long memberId, long reservationId, int peopleCount) {
        ...
    }

메소드 이름으로 메소드의 기능을 파악할 수 있는 것(클린코드 - 의미있는이름)이 가장 좋지만, 명시적으로 표현해 놓았으니 메소드 이름을 보기도 전에 '얘는 읽기 작업을 하는 메소드구나'하고 바로 인지할 수 있다. 물론 이것은 부가적인 효과이다.

오직 읽기 작업(SELECT)만 수행한다.

만약 @Transactional(readOnly = true)이 걸려있는 곳에서 읽기 작업이 아닌 작업을 수행하려 한다면, 쿼리문이 나가지 않는다! 이는 읽기작업을 하는 메소드에서 생성, 수정, 삭제를 하려는 개발자의 실수를 막아준다.

변경감지가 일어나지 않는다.

JPA를 사용한다면 변경감지의 편리함을 알 것이다.

변경 감지란?

JPA는 영속성 컨텍스트에 Entity를 보관할 때 최초의 상태로 저장하는데, 이것을 스냅샷이라고 하며 영속성 컨텍스트가 Flush 되는 시점에 스냅샷과 Entity의 현재 상태를 비교하여 달라진 Entity를 찾는다. 만약 변경된 Entity가 있다면 쓰기지연 SQL 저장소에 변경 쿼리문을 보관했다가, 모든 작업이 끝나면 쓰기지연 SQL저장소에 있는 쿼리를 DB에 전달한다.

그러나 읽기 전용 옵션을 적용하면 스프링은 하이버네이트의 세션 플러시 모드를 MANUAL로 설정한다. 이 모드는 명시적으로 Flush를 호출할 때만 영속성 컨텍스트를 Flush를 하기 때문에 가져온 Entity가 수정되는 일을 막을 수 있다. 그리고 변경감지를 위한 스냅샷을 보관하지 않기 때문에 메모리가 절약되는 성능상 이점도 존재한다.

트랜잭션 ID를 부여하지 않는다.(INNO DB)

MySQL을 이용할 경우 읽기 전용 Transaction에 대한 트랜잭션 ID(트랜잭션을 식별하기 위해 사용되는 고유한 식별자이며 생성, 수정, 삭제 등 여러 작업에서 사용된다) 설정과 관련된 오버헤드를 피할 수 있다. 여기서 오버헤드는 작업을 수행할 때 발생하는 추가적인 비용 또는 쿼리를 실행하는데 사용되는 메모리정도로 생각하면 된다. 이 작업들을 피할 수 있으니 성능상 이점이 생긴것이다.

0개의 댓글