@Transactional과 TransactionTemplate

2024. 5. 17. 09:37Back-End/Spring

트랜잭션 관리(Transaction Management)는 데이터베이스 작업에서 중요한 역할을 한다. 트랜잭션은 일련의 작업을 하나의 논리적 단위로 묶어, 모든 작업이 성공적으로 완료되거나 모두 실패하도록 보장하는 메커니즘이다. 스프링 프레임워크는 트랜잭션 관리를 용이하게 하기 위해 @Transactional 애노테이션과 TransactionTemplate 클래스를 제공한다. 이번 글에서는 이 두 가지 방법에 대해 살펴보고, 각각의 사용법과 차이점을 설명하고자 한다.

 

@Transactional 애노테이션

@Transactional 애노테이션은 선언적 트랜잭션 관리를 제공한다. 이 애노테이션을 사용하면 코드에 최소한의 변경만으로 트랜잭션을 쉽게 적용할 수 있다. 메서드나 클래스 수준에 적용하여 해당 범위 내의 모든 데이터베이스 작업을 트랜잭션으로 처리할 수 있다.

 

@Transactional 애노테이션은 주로 서비스 계층에서 사용되며, 다음과 같은 방식으로 적용할 수 있다.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
        // 다른 데이터베이스 작업들
    }
}

위 예제에서 createUser 메서드에 @Transactional 애노테이션을 적용하여, 해당 메서드 내의 모든 데이터베이스 작업이 하나의 트랜잭션으로 처리되도록 한다. 만약 메서드 실행 중 예외가 발생하면, 트랜잭션이 롤백되어 모든 작업이 취소된다.

 

주요 속성

  • propagation: 트랜잭션의 전파 행동을 정의한다. 예를 들어, REQUIRED, REQUIRES_NEW 등이 있다.
  • isolation: 트랜잭션의 고립 수준을 설정한다. 예를 들어, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE 등이 있다.
  • timeout: 트랜잭션이 완료될 때까지 대기할 최대 시간을 설정한다.
  • readOnly: 읽기 전용 트랜잭션으로 설정하여, 성능을 최적화하고 데이터 변경을 방지한다.

TransactionTemplate 클래스

TransactionTemplate 클래스는 프로그래밍 방식의 트랜잭션 관리를 제공한다. 트랜잭션 템플릿을 사용하면 트랜잭션 경계를 명시적으로 정의할 수 있으며, 트랜잭션 논리를 람다 표현식이나 익명 내부 클래스로 전달할 수 있다.

 

TransactionTemplate 클래스는 주로 상황에 따라 트랜잭션 경계를 동적으로 설정해야 할 때 사용된다. 다음은 TransactionTemplate을 사용하는 예제이다.

import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class OrderService {

    private final TransactionTemplate transactionTemplate;
    private final OrderRepository orderRepository;

    public OrderService(PlatformTransactionManager transactionManager, OrderRepository orderRepository) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.orderRepository = orderRepository;
    }

    public void createOrder(Order order) {
        transactionTemplate.execute(status -> {
            orderRepository.save(order);
            // 다른 데이터베이스 작업들
            return null; // 트랜잭션이 성공적으로 완료되면 null을 반환
        });
    }
}

 

위 예제에서 createOrder 메서드는 TransactionTemplate의 execute 메서드를 사용하여 트랜잭션 경계를 명시적으로 정의한다. 트랜잭션 내에서 수행할 작업은 람다 표현식으로 전달된다.

 

주요 메서드

  • execute(TransactionCallback<T> action): 트랜잭션 경계를 정의하고, 트랜잭션 내에서 실행할 코드를 전달받는다.
  • setPropagationBehavior(int propagationBehavior): 트랜잭션의 전파 행동을 설정한다.
  • setIsolationLevel(int isolationLevel): 트랜잭션의 고립 수준을 설정한다.
  • setTimeout(int timeout): 트랜잭션 타임아웃을 설정한다.
  • setReadOnly(boolean readOnly): 트랜잭션을 읽기 전용으로 설정한다.

@Transactional vs TransactionTemplate

  1. 선언적 트랜잭션 관리 vs 프로그래밍 방식 트랜잭션 관리:
    - @Transactional은 선언적 트랜잭션 관리로, 간단하고 명료하게 트랜잭션을 적용할 수 있다.
    - TransactionTemplate은 프로그래밍 방식으로, 더 유연하고 세밀한 트랜잭션 경계 설정이 가능하다.
  2. 적용 범위:
    - @Transactional은 클래스나 메서드 레벨에 적용할 수 있다.
    - TransactionTemplate은 특정 코드 블록에 트랜잭션을 적용할 수 있다.
  3. 사용 시기:
    - @Transactional은 트랜잭션이 대부분의 메서드에 일관되게 적용될 때 사용한다.
    - TransactionTemplate은 복잡한 트랜잭션 로직이나 동적 트랜잭션 경계 설정이 필요할 때 사용한다.

결론

스프링 프레임워크는 @Transactional TransactionTemplate 통해 다양한 트랜잭션 관리 옵션을 제공한다. @Transactional 선언적 트랜잭션 관리로 간단하게 트랜잭션을 적용할 있으며, TransactionTemplate 프로그래밍 방식으로 유연한 트랜잭션 경계 설정이 가능하다. 애플리케이션의 요구 사항에 따라 적절한 트랜잭션 관리 방식을 선택하여 사용하기를 권장한다.

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

AOP (Aspect-Oriented Programming)  (0) 2024.05.18
ResultSetExtractor  (0) 2024.05.17
배치 업데이트(Batch Update)  (0) 2024.05.17
Spring Data JDBC  (0) 2024.05.16
@Configuration 및 @Bean vs @ComponentScan  (0) 2024.05.14