-
리액티브 프로그래밍에서의 트랜잭션 관리: @Transactional vs TransactionalOperator카테고리 없음 2021. 8. 1. 21:34
리액티브 프로그래밍에서 비동기 데이터 흐름에서 트랜잭션을 안전하게 관리하는 방법에대해 알아보자. R2DBC등의리액티브 데이터베이스 연동에서 트랜잭션 관리는 중요하다. 그런데 MVC 에서 주로 썼던 @Transactional 어노테이션을 그대로 사용해도 될까? TransactionalOperator 클래스는 무엇인지 알아보고 각 접근법의 적합성에 대해서 알아보자.
@Transactional 어노테이션
@Transactional 어노테이션은 전통적인 동기적 트랜잭션 관리에서 널리 사용된다. 이 어노테이션은 메서드의 시작과 끝에서 트랜잭션을 관리하며, 예외 발생 시 트랜잭션을 롤백한다. 그러나 리액티브 프로그래밍 환경에서는 몇 가지 제한이 있다.
- 외부 호출에 의존: @Transactional은 주로 외부 클래스에서 메서드를 호출할 때 트랜잭션을 관리한다. 내부 메서드 호출에서는 트랜잭션이 제대로 적용되지 않을 수 있다.
- 트랜잭션 경계 불명확: 리액티브 체이닝에서 트랜잭션 경계가 명확하지 않아 트랜잭션의 일관성을 보장하기 어렵다.
@Transactional 어노테이션을 사용하는 경우, 비동기적으로 실행되는 리액티브 스트림의 특성상 트랜잭션의 일관성이 보장되지 않을 수 있다. 이는 @Transactional이 전통적인 동기적 트랜잭션 경계를 가정하기 때문이다.
@Transactional
- 전통적인 동기적 트랜잭션 관리: @Transactional은 주로 전통적인 동기적 프로그래밍 환경에서 사용. 스프링은 메서드 진입 시 트랜잭션을 시작하고, 메서드가 종료되면 트랜잭션을 커밋하거나 롤백함
- AOP 기반: @Transactional은 Aspect-Oriented Programming(AOP) 개념을 사용하여 메서드 호출의 앞뒤에 트랜잭션 관리 로직을 삽입한다. 이는 메서드가 호출되기 전에 트랜잭션을 시작하고, 메서드가 정상적으로 종료되면 커밋하며, 예외가 발생하면 롤백하는 방식이다.
- 동기적 코드에 적합: @Transactional은 주로 동기적 트랜잭션 경계를 정의하기 때문에, 리액티브(비동기적) 프로그램에서는 트랜잭션 일관성을 보장하기 어려울 수 있다. 리액티브 스트림의 비동기 특성으로 인해 트랜잭션 경계가 명확히 정의되지 않을 수 있기 때문.
따라서, 리액티브 프로그램에서 트랜잭션의 일관성을 보장하려면 TransactionOperator를 사용하는 것이 더 적합하다.TransactionOperator는 리액티브 스트림 내에서 트랜잭션의 시작과 끝을 명확히 정의할 수 있으며, 데이터베이스 트랜잭션의 커밋 또는 롤백을 정확하게 제어할 수 있다.
TransactionalOperator 클래스
TransactionalOperator는 리액티브 환경에서 트랜잭션을 관리하기 위해 설계된 도구이다. 리액티브 스트림의 트랜잭션 경계를 명확히 설정하고, 비동기 작업의 트랜잭션 일관성을 보장한다.
- 리액티브 프로그래밍에 최적화: TransactionalOperator는 리액티브 스트림의 특성을 고려하여 트랜잭션 상태를 관리한다. 이는 리액티브 스트림 내의 모든 작업이 하나의 트랜잭션으로 처리되도록 보장한다.
- 유연한 제어: 개발자가 트랜잭션 범위를 명시적으로 설정하고 관리할 수 있으며, 필요에 따라 트랜잭션 경계를 조정할 수 있다.
.as(transactionalOperator::transactional)
- 리액티브 트랜잭션 관리: .as(transactionalOperator::transactional)은 리액티브 프로그래밍 환경에서 사용된다. 리액티브 스트림에서 트랜잭션을 시작하고 완료하는 것을 제어한다.
- 리액티브 체이닝 내 트랜잭션 경계 설정: 이 방법은 리액티브 체이닝 내에서 트랜잭션의 범위를 명확히 설정할 수 있습다. .as(transactionalOperator::transactional)를 사용하면 특정 리액티브 스트림의 시작과 끝에서 트랜잭션을 명확히 정의할 수 있으며, 스트림 내에서 발생하는 모든 작업이 하나의 트랜잭션으로 처리된다.
- 비동기 작업에 적합: TransactionOperator는 리액티브 체이닝의 특성을 반영하여 비동기적으로 트랜잭션을 관리한다. 이는 트랜잭션의 시작과 끝을 리액티브 스트림 내에서 자연스럽게 관리할 수 있게 해준다.
리액티브 환경에서 트랜잭션의 일관성을 보장하려면 TransactionalOperator를 사용하는 것이 더 적합하다. @Transactional 어노테이션은 동기적 작업에 유용하지만, 리액티브 체이닝에서는 제약이 있다. 이를 통해 리액티브 프로그래밍에서도 안정적인 트랜잭션 관리가 가능하다.
출처:
https://www.vinsguru.com/spring-data-r2dbc-transaction/
https://spring.io/blog/2019/05/16/reactive-transactions-with-spring