본문 바로가기
Back-End

@Transactional(readOnly = true) 를 사용하는 이유

by 코젼 2025. 5. 19.
728x90
반응형

@Transactional(readOnly = true) 어노테이션은 Spring Framework 에서 제공하는 트랜잭션 설정 중 하나로, 데이터를 읽기 전용으로 사용할 경우 성능 최적화와 데이터 무결성 측면에서 유리합니다.

Spring에서 @Transactional은 하나의 작업 단위를 트랜잭션으로 감싸고, 성공하면 커밋하고 실패 시 롤백하도록 만듭니다. 기본적으로 readOnly = false이며, 데이터 변경 작업(INSERT, UPDATE, DELETE)을 포함할 수 있습니다.

readOnly = true 를 사용하는 이유

장점 설명

💨 성능 향상 dirty checking 생략으로 JPA 처리 속도 향상
🔒 안전성 증가 실수로 DB를 변경하는 것을 방지
⚙️ DB 최적화 DB 힌트를 활용해 락/플랜 최적화 가능 (DB 종속적)

1. 성능 최적화

  • 일부 JPA 구현체 (예: Hibernate)에서는 readOnly = true일 경우 플러시 모드(FlushMode.MANUAL) 를 설정하여, 영속성 컨텍스트의 쓰기 작업 감시를 생략합니다.
  • 따라서 dirty checking을 하지 않아도 되므로 성능이 향상됩니다.
    • 즉, 변경 여부를 추적하지 않음.
  • 특히 조회 전용 서비스 메서드에 적절합니다.

2. 데이터 무결성 보장

  • 개발자 실수로 EntityManager.persist() 또는 Repository.save() 등을 호출해도, 트랜잭션 커밋 시점에 실제 DB 반영이 되지 않습니다.
  • 이를 통해 불필요하거나 의도치 않은 쓰기 작업을 방지할 수 있습니다.

3. 데이터베이스 최적화 (DBMS 종속적)

  • 일부 DB는 read only 트랜잭션 힌트를 기반으로 락 수준을 낮추거나, 쿼리 플랜을 최적화할 수 있습니다.
  • 예: Oracle, MySQL 등 일부 데이터베이스는 읽기 전용 트랜잭션을 더 효율적으로 처리합니다.

클래스 레벨에서 사용할 경우

@Service
@Transactional(readOnly = true)
class Service(
    ...
)

이 설정은 다음을 의미합니다:

  • 이 클래스 내의 모든 메서드에서 기본적으로 읽기 전용 트랜잭션으로 동작함.
  • 즉, flush() 또는 dirty checking을 하지 않고 성능이 더 우수함.
  • 데이터 변경이 없는 조회 메서드에는 적절.

쓰기 작업 메서드에서 @Transactional 로 재정의한 경우\

다음 메서드들은 데이터 변경이 발생하므로 클래스 기본 설정(readOnly = true)을 덮어쓰고 있음:

@Transactional
fun insert(...) { ... }

@Transactional
fun update(...) { ... }

@Transactional
fun delete(...) { ... }

이 경우는 @Transactional(readOnly = false)와 같으며, 다음과 같은 쓰기 관련 동작을 수행할 수 있습니다:

  • EntityManager의 flush(), persist(), merge() 등 데이터베이스 반영
  • 변경 감지(dirty checking)
  • 실제 DB에 INSERT, UPDATE, DELETE 쿼리 전송

구분지어 사용하는 경우

목적 설명

성능 최적화 기본을 readOnly = true로 설정해 조회 메서드의 불필요한 리소스 사용 방지
보안 및 무결성 강화 실수로 조회 메서드에서 데이터 변경 시도하더라도 트랜잭션이 커밋되지 않음
명시적인 의도 표현 변경이 필요한 메서드만 @Transactional로 오버라이딩하여 구분을 명확히 함
관심사 분리 조회 vs 변경을 메서드 레벨에서 쉽게 식별 가능 (리팩터링이나 리뷰에도 유리)

💡 참고: 트랜잭션의 상속 및 오버라이드

Spring에서는 @Transactional이 메서드 → 클래스 → 인터페이스 순서로 적용되며, 메서드 레벨이 우선합니다. 따라서 클래스에 readOnly = true가 있어도, 메서드에 @Transactional만 붙으면 기본값(readOnly = false) 가 적용됩니다.

클래스에서 @Transactional(readOnly = true)를 클래스 수준에서 설정하고, 데이터 변경이 필요한 메서드에만 @Transactional을 재정의한 것은 의도된 성능 최적화 및 안전성 강화 전략입니다. Spring 서비스 레이어에서 많이 사용되는 Best Practice 중 하나입니다.

728x90
반응형

'Back-End' 카테고리의 다른 글

CPU 스케줄링  (1) 2025.05.21
URI, URL, URN  (2) 2025.05.20
디스크 접근 시간  (1) 2025.05.19
해시 충돌  (2) 2025.05.16
방어적 복사  (4) 2025.05.15

댓글