Spring Boot에서 Service 계층을 구현하다 보면
조회 로직에도 @Transactional을 사용하는 경우가 있다.
그런데 조회만 수행하는 메서드에도 일반 @Transactional을 사용하는 것이 적절한지 고민하게 되었다.
그래서 조회 로직에서 @Transactional(readOnly = true)를 사용하는 이유를 정리해보려고 한다.
상황
조회 로직에서는 데이터를 수정하는 것이 아니라
단순히 데이터를 조회만 수행하는 경우가 많다.
이때 Service 메서드에 일반 @Transactional을 사용하면
JPA 구현체인 Hibernate가 조회한 데이터가 변경되었는지 확인하는 작업을 수행한다.
하지만 조회만 하는 메서드에서는 이러한 확인 작업이 필요하지 않기 때문에
@Transactional(readOnly = true) 옵션을 사용하는 것이 더 적절하다고 생각했다.
예를 들어 식당 단건 조회 로직은 다음과 같이 구현하였다.
@Transactional(readOnly = true)
public StoreResponse getStore(Long storeId) {
Store store = findStoreById(storeId);
return StoreResponse.from(store);
}
이 메서드는 데이터를 수정하는 로직이 아니라
단순히 식당 정보를 조회하는 기능이기 때문에 readOnly 옵션을 사용하였다.
readOnly 옵션의 특징
readOnly = true 옵션을 사용하면
해당 트랜잭션을 읽기 전용 트랜잭션으로 설정할 수 있다.
이 경우 Hibernate가 데이터 변경 여부를 확인하는 작업을 수행하지 않는다.
따라서 불필요한 과정이 줄어들어
조회 로직을 조금 더 효율적으로 실행할 수 있다.
또한 코드만 보아도 해당 메서드가
조회 전용 로직이라는 것을 명확하게 표현할 수 있다.
정리
조회만 수행하는 Service 메서드에서는
@Transactional(readOnly = true)
옵션을 사용하여
- 데이터가 변경되었는지 확인하는 불필요한 작업을 줄이고
- 조회 전용 로직임을 명확하게 표현할 수 있다.
따라서 조회 로직에서는 @Transactional(readOnly = true)를 사용하고,
데이터를 변경하는 로직에서는 일반 @Transactional을 사용하는 방식으로
트랜잭션을 구분해서 사용하는 것이 좋다고 이해했다 !!
'트러블슈팅' 카테고리의 다른 글
| 조회 성능 개선 1단계 - Pageable 적용 (0) | 2026.03.17 |
|---|---|
| 조회 API 응답 속도가 느린 이유 분석 (Postman 테스트 기반) (0) | 2026.03.17 |
| Spring JPA에서 findById() 예외 처리는 Service에서 해야 할까? Repository에서 해야 할까? (0) | 2026.03.11 |
| JPA 연관관계 설계 트러블슈팅 (0) | 2026.03.06 |
| GitHub Issue Template이 표시되지 않는 문제 해결 (front-matter 설정) (0) | 2026.03.06 |