조회한 데이터를 return 한다고 해도 의도치 않게 데이터가 변경되는 일을 사전에 방지해줍니다.
해당 옵션인 경우 CUD 작업이 동작하지 않고, 스냅샷 저장, 변경 감지(dirty check)의 작업을 수행하지 않아 성능이 향상됩니다. 여기서 dirty checking은 상태 변경검사인데요, dirty란 상태의 변화가 생긴 정도라고 이해하면 될 것 같습니다.
JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해줍니다. JPA에서는 엔티티를 조회하면 해당 엔티티의 처음 조회 상태 그대로 스냅샷을 만들어놓습니다. 그리고 트랜잭션이 끝나는 시점에는 이 스냅샷과 비교해서 다른 점이 있다면 Update Query를 데이터베이스로 전달합니다. - 이동욱 님 블로그
MySQL을 사용할 때 데이터가 날아가는 것을 방지하기 위해서 이중화 구성(master - Slave)을 하는 경우가 있는데 DB가 master와 slave로 나누어져 있다면 readOnly = true로 있는 경우에는 읽기 전용으로 master가 아닌 slave를 호출하게 됩니다. 즉, 상황에 따라 DB 서버의 부하를 줄이고 약간의 최적화를 할 수 있습니다.
@Transactional(readOnly=true) 어노테이션이 있다면 코드를 접하는 사람들이 직관적으로 보기에 해당 메서드는 READ에 대한 동작만 수행할 것이라고 예상합니다. 그리고 결과적으로도 읽기 동작만 수행이 되죠. 또한 이 어노테이션을 보고 누구나 한눈에 알아볼 수 있고, 신뢰성을 보장한다고 받아들입니다.