인프런 커뮤니티 질문&답변

최시영님의 프로필 이미지

작성한 질문수

실전! 스프링 데이터 JPA

JPA Hint & Lock

@QueryHint의 readOnly 와 @Transaction의 readOnly 차이

20.04.14 16:10 작성

·

2.4K

41

안녕하세요. @QueryHint 의 readOnly 속성과 관련하여 질문있습니다.

이전의 강의(jpa 활용 1편) 에서 service 단에 @Transaction(readOnly=true) 설정을 주었을 때

영속성 context flush (X), dirty checking (X) 를 통해서 성능을 최적화하고 DB에 읽기 전용임을 알린다고 배운게 기억이 나서요.

정리하자면 

1. @QueryHint 의 readOnly 속성은

(how) 스냅샷을 만들지 않음으로써 

(what) Dirty Checking의 비교를 하기 위해 내부적으로 객체를 2개(스냅샷) 만들어 메모리 낭비하는 것을 방지

2. @Transaction(readOnly=true) 속성은

(how) DB에 반영할 것이 없다는 것을 암시하여 영속성 context flush 를 하지 않도록 하여 

(what) dirty checking 안 함 -> 성능 최적화

으로 이해를 했는데요. 왠지 두가지 방법이 매우 유사한 것 같아 이와 관련하여 구글링 하던 중 

https://vladmihalcea.com/spring-read-only-transaction-hibernate-optimization/

위 글을 봤는데 

제가 이해하기로는 위 글에서 얘기하는 Entity loaded state 가 말씀하신 스냅샷이고 강의와 동일하게 'queryHint-readOnly를 통해 생성을 막을 수 있다.' 라고 하면서

작성자 본인이 기존에 Transactional-readOnly를 사용했을 때 Entity loaded state(스냅샷) 생성이 막히지 않아 git pull 요청을 해서 spring 5.1에서 적용됐다는 것 같은데요.

제가 이해한게 맞는지 그렇다면 @Transaction(readOnly=true)를  @QueryHint-readOnly속성과 동일한 기능으로 보고 대체하여 사용할 수 있는지 궁금합니다.

감사합니다.

답변 2

40

김영한님의 프로필 이미지
김영한
지식공유자

2020. 04. 14. 22:34

안녕하세요. 최시영님 좋은 질문입니다.

@QueryHint의 readOnly는 스냅샷을 만들지 않기 때문에, 메모리가 절약됩니다.

그리고 @Transaction(readOnly=true)는 트랜잭션 커밋 시점에 flush를 하지 않기 때문에 이로 인한 dirty checking 비용이 들지 않습니다. 따라서 cpu가 절약됩니다.

따라서 읽기 전용 데이터는 이 두가지를 조합하면 최적의 성능 최적화를 얻을 수 있습니다.

(JPA 책 15.4.2 읽기 전용 쿼리의 성능 최적화에서 관련 내용을 다루고 있습니다.)

사실 생각해보면 @Transaction(readOnly=true)만 되어 있으면 이 내용을 보고 @QueryHint의 readOnly를 자동으로 넣어주면 진행하면 귀찮은 @QueryHint를 생략해도 되겠지요. (엔티티매니저에 readOnly 힌트를 주면 되겠지요)

이전에 글을 보아서, 저도 시간이 있으면 한번 쭉 검증해볼 것 같은데, 엔티티만 조회용으로 딱 사용하는 경우가 많지는 않아서, 따로 확인해보지는 않았습니다. 추가로 책에서도 설명하지만, 엔티티가 아니라 DTO로 바로 조회할 때는 어차피 스냅샷이 안만들어지기 때문에 이 경우에는 성능 이점이 없습니다.

감사합니다^^

(혹시 검증해보시고, 잘 돌아가면 꼭 공유부탁드려요!)

===추가===

방금 돌려봤는데, 잘 동작하네요. 스프링 5.1 버전 이후를 사용하시면 @Transaction(readOnly=true)로 설정하시면, @QueryHint의 readOnly까지 모두 동작한다고 보시면 됩니다^^ 질문해주신 덕분에 저도 돌려보고 하나 배웠네요 ㅎㅎ 감사합니다.

12

최시영님의 프로필 이미지
최시영
질문자

2020. 04. 15. 14:08

안녕하세요. 답변과 확인 감사합니다!

git 요청으로 업데이트 되는 걸 간접적으로나마  보니까 스프링이 오픈소스라는 걸 실감하게 되네요ㅎㅎ

어쨋든 실무에서는 엔티티만 조회하는 경우보다 DTO로 조회하는 경우가 많아 성능 최적화를 위해 readOnly를 사용할 일이 잘 없다는 거군요. 거기까지는 생각을 못 했습니다ㅎㅎ

DTO로 조회할 때는 스냅샷이 만들어지지 않는 것도 어떻게 보면 당연한 건데 생각을 못 했네요ㅠ

강의가 매우 깊고 알차서 잘 배우고 있습니다. 감사합니다!