본문 바로가기
공부/Spring

[Spring] @Transactional

by JERO__ 2022. 4. 29.

1. 트랜잭션이란? (ACID)

  • 하나의 논리적 작업 단위로 수행되는 일련의 작업
  • 일련의 작업이 모두 하나의 논리적 작업으로 취급되기 때문에 논리적 작업을 취소하면, 그 내부에 포함된 일련의 작업들이 모두 취소된다.

2. 테스트코드에서의 @Transactional 사용

  • 역할 : DB와 관련된 테스트코드를 작성하면 테스트메서드에 @Transactional을 사용하여 테스트 메서드가 종료될 때 생성된 DB 커밋을 rollback한다.
  • @Transactional 을 사용하지 않고 @Service테스트를 실행하면?
    • 테스트 메서드 내부에서 사용했던 데이터들이 남게되어 실제 서비스에 영향을 미칠 수 있어 지워야할 필요가 있다.
  • DB에 반영하고 싶다면 @Rollback(false)
  • auto_increment나 sequence 등에 의해 증가된 값은 롤백이 되지 않는다.
    • 별도의 데이터베이스로 연결을 하거나 또는 H2와 같은 휘발성(인메모리) 데이터베이스를 사용하여 해결

3. 프로덕션 코드에서의 @Transactional 사용

3-1. 일반적으로 비지니스 로직을 담고 있는 서비스 계층의 메소드와 결합시키는 것이 좋음

  • 데이터 저장 계층으로부터 읽어온 데이터를 사용하기 때문
  • 데이터를 사용하고 변경하는 등의 작업을 하는 곳이기 때문

3-2. 읽기 전용 트랜잭션의 공통화 (SELECT) : 사용권장!

  • @Transactional(readOnly = true)
    • SELECT 문에 대해서만 기능을 지원
    • 스냅샷을 통해 데이터 일관성을 보장
    • CUD 작업이 동작하지 않아(스냅샷을 저장하기에) 변경 감지등의 작업을 수행하지 않음으로 성능이 향상
  • final을 두어 객체의 신뢰성을 보장하는 것과 비슷하다!

3-3. 그렇다면 그 외의 경우? CUD (Create, Update, Delete)

참고내용

  • 단일 객체의 쓰기 : 일반적으로 쓰이는 트랜잭션의 의미는 아니다(다중 연상을 하나의 실행단위로 묶는 매커니즘이기 때문)
    • 과도한 트랜잭션 처리는 성능에 불리하다.
  • 다중 객체 트랜잭션
    • 성능 vs 무결성/관리비용 : 둘 중 무엇이 더 중요한지 판단하여 적절한 격리 수준을 적용하는 것이 중요하다!
    • 트랜잭션은 꼭 필요한 최소의 코드에 적용하는 것이 좋다. (https://elky84.github.io/2020/02/07/db_transaction/)

4. 결론

  • SELECT쿼리인 경우, @Transactional(readOnly = true)를 사용하면 다른 트랜잭션 사용과 다르게 성능이 향상되기에 사용을 권장한다.
  • 무결성/관리비용의 중요성이 낮은 서비스는 트랜잭션을 적용하지 않는다. 적절한 트랜잭션 적용이 필요하다. -> 성능이슈(Transaction은 많은 Cost를 발생시킨다)

댓글