Spring/Spring

[Spring][Data Access] 1-1. Transaction Manager: Advantages of the Spring Framework’s Transaction Support Model

noahkim_ 2024. 8. 11. 04:30

1. Global Transactions (Distributed Transactions)

  • 여러 트랜잭션 리소스를 하나의 트랜잭션으로 묶어 관리
  • 여러 자원간의 데이터 일관성 유지가 목적

 

JTA (Java Transaction API)

항목 설명
설명
Java에서 전역 트랜잭션을 관리하기 위한 표준 API
용도
분산 환경에서의 트랜잭션을 통합적으로 관리 (예: 여러 DB, 메시지 큐 등)
주요 클래스
UserTransaction, TransactionManager 등
사용 방식
JNDI를 통해 UserTransaction 객체를 주입받아 트랜잭션 제어
단점
- 복잡성: 예외 처리, 롤백 시나리오 등이 복잡함
- 의존성: JNDI를 통한 객체 주입이 필요 (환경 설정 및 컨테이너 종속성)

예제) UserTransaction

더보기
public class JTADemo {
    public static void main(String[] args) {
        UserTransaction userTransaction = null;
        try {
            // JNDI를 통해 UserTransaction 객체를 주입받아야 함
            InitialContext context = new InitialContext();
            userTransaction = (UserTransaction) context.lookup("java:comp/UserTransaction");
            
            // 트랜잭션 시작
            userTransaction.begin();

            // 비즈니스 로직 수행 (예: 여러 데이터베이스에 걸친 작업)
            performBusinessLogic();

            // 트랜잭션 커밋
            userTransaction.commit();

        } catch (Exception e) {
            // 예외 발생 시 트랜잭션 롤백
            try {
                if (userTransaction != null) {
                    userTransaction.rollback();
                }
            } catch (Exception rollbackEx) {
                System.out.println("Rollback failed: " + rollbackEx.getMessage());
            }
            System.out.println("Transaction failed: " + e.getMessage());
        }
    }

    private static void performBusinessLogic() throws Exception {
        // 예외를 던질 수 있는 비즈니스 로직
        System.out.println("Executing business logic...");
        // 예를 들어, 데이터베이스 작업 중 예외 발생 가능
        if (Math.random() > 0.5) {
            throw new Exception("Simulated business logic failure");
        }
        System.out.println("Business logic completed successfully.");
    }
}

 

EJB CMT (Enterprise JavaBeans Container Managed Transations)

항목 설명
설명
트랜잭션 처리를 EJB 컨테이너가 대신 수행하는 방식
관리 주체
EJB 컨테이너
트랜잭션 제어 방법
선언적으로 트랜잭션을 정의 (@TransactionAttribute, ejb-jar.xml)
사용 대상
EJB 컴포넌트 (예: Session Bean)
장점 - 선언적 트랜잭션 관리: 트랜잭션 코드를 작성하지 않고 애너테이션이나 설정만으로 트랜잭션 정의 가능
- 자동 트랜잭션 처리: begin/commit/rollback 등을 컨테이너가 자동 수행
단점 - 의존성: JNDI 및 EJB 컨테이너 환경에 강하게 의존함
- 유연성 부족: 내부적으로 JTA에 강하게 결합됨

예시) @TransactionAttribute

더보기
@Stateless
public class CMTExampleBean {

    // EJB CMT를 사용하여 선언적으로 트랜잭션을 관리
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void performTransaction() {
        // 비즈니스 로직 수행
        System.out.println("Performing business logic inside a container-managed transaction.");

        // 예외가 발생하면 컨테이너가 자동으로 트랜잭션을 롤백
        if (Math.random() > 0.5) {
            throw new RuntimeException("Simulated failure");
        }

        System.out.println("Business logic executed successfully.");
    }
}

 

2. Local Transactions

항목 설명
설명
특정 트랜잭션 자원과 직접 연결된 로컬 트랜잭션 (예: JDBC, JMS 등)
관리 주체
개발자 (수동 코드로 직접 트랜잭션 제어)
지원 범위
단일 자원
장점
- 간단함: 단일 자원에 대해 설정이 간단하여 빠르게 설정할 수 있음
단점
- 침습성: 트랜잭션 코드(begin(), commit(), rollback())를 직접 작성해야 함
- 확장성 부족: 다중 자원 간 트랜잭션 불가 (JTA 같은 분산 트랜잭션 기술과 연동 불가능)
예시) JDBC API
더보기
Connection conn = dataSource.getConnection();
try {
    conn.setAutoCommit(false); // 트랜잭션 시작

    // SQL 실행
    stmt1.executeUpdate();
    stmt2.executeUpdate();

    conn.commit(); // 성공 시 커밋
} catch (Exception e) {
    conn.rollback(); // 실패 시 롤백
} finally {
    conn.close(); // 연결 종료
}

 

3. Spring Framework’s Consistent Programming Model

항목 설명
설명
EJB 없이도 독립적인 트랜잭션 관리가 가능하며,
일관된 방식으로 로컬/전역 트랜잭션 처리를 지원함
지원 방식
선언적 트랜잭션 (@Transactional, XML), 프로그래밍 방식 모두 지원
트랜잭션 추상화
PlatformTransactionManager를 통해 다양한 트랜잭션 구현체 추상화
적용 범위
로컬 트랜잭션 + 전역 트랜잭션 모두 처리 가능

예시) 설정

더보기

1. 설정클래스 정의

@Configuration
@EnableTransactionManagement
public class AppConfig {
    // TransactionMananger 관련 빈 등록하기
}
  • @EnableTransactionManagement: 애노테이션 기반 트랜잭션 관리 활성화

 

2. TransactionManager 설정

@Bean
public PlatformTransactionManager transactionManager() {
    return new JtaTransactionManager();
}

 

항목 설명
PlatformTransactionManager
Spring의 트랜잭션 추상화 인터페이스
다양한 트랜잭션 전략을 일관되게 처리 (JDBC, JTA 등)
JtaTransactionManager
PlatformTransactionManager의 구현체 중 하나
전역 트랜잭션(JTA) 처리를 지원

 

3. 트랜잭션 속성 설정

@Bean
public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
    Properties transactionAttributes = new Properties();

    // 모든 메서드에 대해 REQUIRED 속성을 적용
    transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");

    TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
    transactionInterceptor.setTransactionManager(transactionManager);
    transactionInterceptor.setTransactionAttributes(transactionAttributes);

    return transactionInterceptor;
}
항목 설명
TransactionInterceptor 트랜잭션 인터셉터를 설정
PROPAGATION_REQUIRED 트랜잭션이 이미 존재하면 참여, 없으면 새 트랜잭션 생성

 

4. 트랜잭션 어드바이스를 자동으로 적용할 프록시 생성기 Bean 지정

@Bean
public BeanNameAutoProxyCreator transactionAutoProxy() {
    BeanNameAutoProxyCreator proxyCreator = new BeanNameAutoProxyCreator();
    proxyCreator.setInterceptorNames("transactionInterceptor");
    proxyCreator.setBeanNames("*Service");  // 예: 서비스 계층에 트랜잭션을 적용
    return proxyCreator;
}
  • BeanNameAutoProxyCreator: 자동 프록시 생성기. 어드바이스, 포인트컷 설정 가능

 

예시) 선언적 트랜잭션

더보기
@Service
public class ExampleService {

    @Transactional // 이 메서드는 트랜잭션 내에서 실행됨
    public void executeInTransaction() {
        // 트랜잭션 내에서 실행될 비즈니스 로직
        System.out.println("Executing business logic within a transaction.");
    }
}

 

 

예시) 일관된 프로그래밍 모델

더보기
@Service
public class TransactionalService {

    @Autowired
    private JdbcTemplate jdbcTemplate; // 로컬 트랜잭션 사용

    @Transactional
    public void performDatabaseOperation() {
        // 로컬 트랜잭션에 대한 작업 수행
        jdbcTemplate.update("INSERT INTO my_table (column1) VALUES (?)", "Value1");

        // 로컬 트랜잭션과 전역 트랜잭션 간의 코드 차이가 없음
        System.out.println("Database operation performed in a transaction.");
    }
}

 

출처