스프링 트랜잭션 관리의 핵심 원리와 활용

트랜잭션 관리는 많은 개발자들이 익숙해진 주제지만, 실제 구현 및 설계 원리를 깊이 이해하는 것은 매우 중요합니다. 이 글에서는 스프링 트랜잭션 관리의 핵심 개념과 그 설계 철학을 살펴보겠습니다.

왜 트랜잭션 관리가 필요한가?

트랜잭션 관리기가 없다면 여러 데이터베이스 작업을 하나의 트랜잭션으로 관리하려면 다음과 같은 코드를 작성해야 합니다:
// 메서드A
public void methodA(){
    Connection conn = getConnection();
    try{
        int updated = conn.prepareStatement().executeUpdate();
        methodB(conn);
        conn.commit();
    }catch (Exception e){
        rollback(conn);
    }finally {
        releaseConnection(conn);
    }
}

// 메서드B
public void methodB(Connection conn){
    int updated = conn.prepareStatement().executeUpdate();
}

또는 ThreadLocal을 사용하여 연결을 관리할 수도 있습니다:
static ThreadLocal<Connection> connHolder = new ThreadLocal<>();

// 메서드A
public void methodA(){
    Connection conn = getConnection();
    connHolder.set(conn);
    try{
        int updated = conn.prepareStatement().executeUpdate();
        methodB();
        conn.commit();
    }catch (Exception e){
        rollback(conn);
    }finally {
        releaseConnection(conn);
        connHolder.remove();
    }
}

// 메서드B
public void methodB(){
    Connection conn = connHolder.get();
    int updated = conn.prepareStatement().executeUpdate();
}

하지만 이러한 접근법은 복잡해질수록 유지보수가 어려워집니다. 이런 문제를 해결하기 위해 스프링은 트랜잭션 관리자를 제공합니다.

스프링 트랜잭션 관리가 해결하는 문제

스프링 트랜잭션 관리는 JDBC의 Connection, Hibernate의 Session, MyBatis의 SqlSession 등의 리소스를 관리하며, 복잡한 트랜잭션 시나리오에서도 안정적인 동작을 보장합니다.

트랜잭션 전파 행동(Propagation Behavior)

트랜잭션 전파 행동은 호출된 메서드가 현재 트랜잭션을 사용할지 새로운 트랜잭션을 시작할지를 결정합니다. 예를 들어, @Transactional 애노테이션을 사용하면 간단하게 설정할 수 있습니다:
@Transactional
public void methodA(){
    jdbcTemplate.batchUpdate(updateSql, params);
    methodB();
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB(){
    jdbcTemplate.batchUpdate(updateSql, params);
}

트랜잭션 롤백

기본적으로 스프링의 트랜잭션 관리는 예외 발생 시 자동 롤백됩니다. 그러나 특정 예외에 대해 롤백을 방지하고 싶다면 다음처럼 설정할 수 있습니다:
@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
public void methodB(){
    jdbcTemplate.batchUpdate(updateSql, params);
}

트랜잭션 관리 모델

스프링의 트랜잭션 관리는 PlatformTransactionManager 인터페이스를 통해 정의되며, 이 인터페이스는 세 가지 핵심 기능을 제공합니다: 트랜잭션 리소스 획득, 커밋, 롤백.
interface PlatformTransactionManager{
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}

자동 및 수동 트랜잭션 관리

스프링은 XML AOP, @Transactional 애노테이션, 그리고 TransactionTemplate을 통해 트랜잭션을 관리할 수 있도록 지원합니다. 특히 TransactionTemplate을 사용하면 매우 유연하게 트랜잭션을 제어할 수 있습니다:
Integer rows = new TransactionTemplate(transactionManager, 
    new DefaultTransactionDefinition(TransactionDefinition.ISOLATION_READ_UNCOMMITTED))
    .execute(status -> {
        int rows0 = jdbcTemplate.update(...);
        int rows1 = jdbcTemplate.update(...);
        return rows0 + rows1;
    });

이러한 다양한 방법을 통해 스프링 트랜잭션 관리는 복잡한 트랜잭션 요구사항에도 쉽게 대응할 수 있게 해줍니다.

태그: Spring 트랜잭션-관리 PlatformTransactionManager TransactionTemplate @Transactional

8월 12일 20:33에 게시됨