spring

[Spring] Spring의 트랜잭션 동기화(Transaction Synchronization)

goblin- 2024. 11. 28. 10:34

Spring에서는 트랜잭션 관리가 핵심 기능 중 하나로, 데이터베이스 작업을 안정적으로 처리하고 데이터 일관성을 유지하기 위해 다양한 기능을 제공합니다. **트랜잭션 동기화(Transaction Synchronization)**는 이러한 트랜잭션 관리에서 중요한 역할을 하는 개념 중 하나입니다.

 

1. 트랜잭션 동기화란?

 

트랜잭션 동기화는 하나의 트랜잭션이 여러 작업(예: SQL 실행, 자원 관리 등)을 수행하는 동안 자원을 효율적으로 관리하기 위해 트랜잭션과 관련된 자원(주로 데이터베이스 Connection)을 하나의 컨텍스트(Context)에서 관리하는 방식입니다.

Spring은 TransactionSynchronizationManager 클래스를 사용하여 트랜잭션 컨텍스트에 자원을 동기화합니다.

 

2. 트랜잭션 동기화의 핵심 개념

 

1. TransactionSynchronizationManager:

Spring에서 트랜잭션 상태와 자원을 관리하는 유틸리티 클래스입니다.

트랜잭션이 시작되면 TransactionSynchronizationManager가 트랜잭션 컨텍스트를 생성하고, 필요한 자원(Connection, EntityManager)을 해당 컨텍스트에 바인딩합니다.

2. 트랜잭션 컨텍스트:

특정 트랜잭션과 관련된 자원(예: 데이터베이스 연결, 캐시 등)을 저장하는 논리적인 공간입니다.

트랜잭션이 종료되면 해당 자원들은 정리(cleanup)됩니다.

3. ThreadLocal:

트랜잭션 동기화는 ThreadLocal을 사용하여 현재 실행 중인 스레드와 트랜잭션 컨텍스트를 연결합니다.

따라서 한 스레드 내에서는 트랜잭션 범위에서 동일한 자원을 공유할 수 있습니다.

4. 트랜잭션 참여:

같은 스레드에서 동일한 트랜잭션을 사용하는 여러 DAO(Data Access Object)들이 동일한 Connection을 공유할 수 있도록 지원합니다.

이를 통해 불필요한 커넥션 생성을 방지하고 성능을 최적화합니다.

 

3. 트랜잭션 동기화의 동작 과정

 

예: 트랜잭션 관리와 데이터베이스 연결

 

1. 트랜잭션 시작:

@Transactional 어노테이션 또는 트랜잭션 API를 사용하여 트랜잭션이 시작됩니다.

Spring은 TransactionSynchronizationManager를 통해 트랜잭션 컨텍스트를 생성하고 관리합니다.

2. 트랜잭션 컨텍스트에 자원 바인딩:

트랜잭션이 시작되면 DataSource에서 Connection을 가져와 트랜잭션 컨텍스트에 바인딩합니다.

Connection은 트랜잭션 동안 공유되며, 동일한 트랜잭션에서 다른 DAO 호출 시 재사용됩니다.

3. 작업 수행:

여러 DAO나 서비스에서 동일한 트랜잭션을 사용하여 데이터베이스 작업을 수행합니다.

이 과정에서 동일한 Connection이 사용되어 트랜잭션의 일관성을 유지합니다.

4. 트랜잭션 커밋 또는 롤백:

작업이 성공하면 commit()을 호출하여 모든 변경 사항을 데이터베이스에 반영합니다.

작업이 실패하면 rollback()을 호출하여 트랜잭션 시작 이전 상태로 복원합니다.

5. 트랜잭션 종료:

TransactionSynchronizationManager는 트랜잭션이 종료되면 컨텍스트에서 자원을 정리하고 반환합니다.

 

4. 트랜잭션 동기화의 이점

 

1. 효율적인 자원 관리:

트랜잭션 동안 동일한 Connection이나 EntityManager를 공유하여 자원을 효율적으로 사용합니다.

2. 코드의 단순화:

DAO나 서비스 간에 Connection을 전달하지 않아도 되므로 코드가 간결해집니다.

3. 트랜잭션 범위에서 자원 일관성 유지:

모든 데이터베이스 작업이 동일한 트랜잭션 컨텍스트 내에서 처리되므로 데이터의 일관성이 보장됩니다.

4. 여러 DAO 통합 지원:

여러 DAO가 하나의 트랜잭션에 참여할 수 있도록 지원하여, 복잡한 비즈니스 로직을 쉽게 처리할 수 있습니다.

 

5. 트랜잭션 동기화 예제

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private PaymentRepository paymentRepository;

    @Transactional
    public void placeOrder(Order order, Payment payment) {
        // 트랜잭션 시작: TransactionSynchronizationManager가 트랜잭션 컨텍스트 생성
        orderRepository.save(order); // 같은 Connection 사용
        paymentRepository.process(payment); // 같은 Connection 사용
        // 트랜잭션 종료 시 커밋 또는 롤백
    }
}

위 코드에서 orderRepositorypaymentRepository는 모두 같은 Connection을 사용합니다.

트랜잭션 실패 시, 두 작업 모두 롤백됩니다.

 

6. 주의사항

 

Nested Transactions:

Spring은 기본적으로 중첩 트랜잭션을 지원하지 않으며, 동일한 스레드 내에서 하나의 트랜잭션 컨텍스트를 공유합니다.

프로퍼티 설정:

spring.datasourcespring.jpa 설정을 통해 데이터베이스 연결 풀 및 트랜잭션 관리 전략을 조정해야 합니다.

ThreadLocal:

스레드 간 트랜잭션 컨텍스트를 공유할 수 없으므로, 트랜잭션은 동일한 스레드에서만 작동합니다.

 

7. 트랜잭션 동기화의 한계와 해결 방법

 

한계:

기본적으로 단일 데이터베이스 내에서만 트랜잭션 동기화가 가능합니다.

분산 트랜잭션(여러 데이터베이스 또는 시스템 참여)이 필요한 경우 추가적인 설정과 기술(예: JTA)이 필요합니다.

해결 방법:

Spring에서 JTA(Java Transaction API)를 사용하여 분산 트랜잭션을 처리하거나, 특정 분산 트랜잭션 관리자를 도입합니다.

 

결론

 

Spring의 트랜잭션 동기화는 트랜잭션을 효과적으로 관리하고, 자원의 일관성과 효율성을 높이기 위한 강력한 도구입니다. TransactionSynchronizationManager를 통해 트랜잭션 컨텍스트에 자원을 동기화하고, DAO 간 연결 공유 및 일관된 데이터 작업을 지원합니다. @Transactional 어노테이션을 사용하면 대부분의 트랜잭션 관련 작업이 간단하게 처리되므로 현대 개발 환경에서 널리 사용됩니다.