[Spring] @Transactional의 탄생배경

목포·2023년 2월 25일
1

Spring 프레임워크를 쓰는 이유 중 하나는 트랜잭션 관리 기능 지원 때문일 것이다. Spring 이전의 EJB 환경 개발은 JNDI가 필수적이었으며 그만큼 xml 스키마의 작성량도 많았을 것이다. JTA(Java Transaction API)또한, JNDI를 사용해야했고 이 때문에 전역 트랜잭션을 사용할 때 코드 재사용에 어려움이 있다는 단점이 있었다고 한다.

여기서 전역(글로벌) 트랜잭션을 잠깐 설명하자면, 트랜잭션에 참여한 일들 중 하나라도 다른 리소스에서 발생했을 때를 말한다. 예를들어, 서로 다른 은행 간의 이체 작업을 해야하는 경우가 그렇다. 보통 XA라고도 부르며 2개의 phase commit을 통한 분산 트랜재션 처리를 위한 표준이다.

트랜잭션은 보통 begin -> end -> prepare -> commit의 과정을 거치는데 트랜잭션의 원자성을 보장하기 위해 지원하는 분산 알고리즘을 2PC라고 부른다. 즉, 둘 이상의 리소스에 대한 트랜잭션 이 전부 다 커밋되는가 전부 다 롤백되는가에 대한 문제인 것이다.
그림에서처럼 Phase1에서 모든 DB에 반영할 수 있는지 확인하는 과정을 거치고 합의가 되지 않으면 롤백한다. 때문에 데이터가 쓰기 시작하는 순간 부터 커밋될 때까지는 락이 걸려있다. 락을 통해 정합성을 보장하는 것이다.

Spring Transaction 추상화

그래서 Spring이 등장한 후 트랜잭션에 관한 코드가 추상화되었다. SPI(Service Provider Interface) 방식으로 작성되며 두 번째 코드 블럭과 같이 사용할 수도 있다. 덕분의 IoC Container를 통한 Bean 전략을 트랜잭션에 적용할 수 있게되었고, JTA를 직접 사용할 필요가 없게되었다.

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(
            TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
    // execute your business logic here
}
catch (MyException ex) {
    txManager.rollback(status);
    throw ex;
}
txManager.commit(status);

하지만, 이런 코드 기반의 트랜잭션 선언은 비지니스 코드와 결합이되어 2가지 책임을 가지게된다. 때문에 등장한 것이 지금 우리가 많이 알고 있는 AOP 기반의 분리된 선언적 트랜잭션(@Transactional)이다.
이 선언적 트랜잭션은 개별 메서드 수준까지 사용할 수 있기 때문에 EJB CMT(컨테이너 관리 트랜잭션)와 유사한 면이 있다고 한다. (EJB CMT는 위에서 말한 Spring 등장 이전 글로벌 트랜잭션을 관리하기 위한 방법이었다고 보면 된다.)

@Trancational
public void saveObject() {
	...
}

단순히 @Transactional이라는 어노테이션을 통해 트랜잭션을 컨트롤하는 환경에서 개발을 하고 있어, 그 이전의 탄생 배경에 대한 이해가 전혀 없는 상태였는데 이 부분을 알아보면서 EJB환경에서의 트랜잭션 추상화를 하기 위해서 (즉, EJB CMT)JBOSS나 WEBLOGIC같은 J2EE 스펙을 지원하는 미들웨어를 사용해야 했다는 사실을 알게되었다. 꽤나 legacy한 기술을 사용하는 곳에선 아직도 사용하고 있기 때문에 이 관리 기술이 왜 이렇게 진화해왔는지를 이해할 수 있게 된 것 같다.

출처

https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

profile
mokpo devlog

0개의 댓글