본문 바로가기

Java/Spring

[Spring] Transaction 정리, 설정

Transaction 

- 비즈니스에서는 쪼개질 수 없는 하나의 단위 작업을 말할 때 '트랜잭션(Transaction)'이라는 용어를 사용한다.

- 사전적인 의미로 트랜잭션은 '거래'라는 뜻을 가지지만, 현실적으로는 '한 번에 이루어지는 작업의 단위'를 트랜잭션으로 간주한다.

 

ACID원칙

원자성(Atomicity) 하나의 트랜잭션은 모두 하나의 단위로 처리되어야 한다. 좀 더 쉽게 말하자면 어떤 트랜잭션이 A와 B로 구성된다면 항상 A, B로 구성된다면 항상 A, B의 처리 결과는 동일 결과이어야 한다. 즉, A는 성공했지만, B는 실패할 경우 A, B 모두 원래 상태로 되돌려져야 한다. 어떤 작업이 잘못되는 경우 모든 것은 다시 원점으로 돌아가야 한다.
일관성(Consistency) 트랜잭션이 성공했다면 데이터베이스의 모든 데이터는 일관성을 유지해야만 한다. 트랜잭션으로 처리된 데이터와 일반 데이터 사이에는 전혀 차이가 없어야만 한다.
격리(Isolotaion) 트랜잭션으로 처리되는 중간에 외부에서의 간섭은 없어야만 한다.
영속성(Durability) 트랜잭션이 성공적으로 처리되면, 그 결과는 영속적으로 보관되어야만한다.

 

for instance

트랜잭션에 가장 흔한 예제는 '계좌 이체'이다.

- '계좌 이체'라는 행위가 내부적으로는 하나의 계좌에서는 출금이 이루어져야 하고, 이체의 대상 계좌에서는 입금이 이루어져야만 한다.

- '출금'과 '입금'이라는 각각의 거래가 하나의 단위를 이루게 된다.

 

- 비즈니스에서 하나의 트랜잭션은 데이터베이스 상에서는 하나 혹은 여러 개의 작업이 같은 묶음을 이루는 경우가 많다. 예를 들어 비즈니스 계층에서는 '계좌 이체'는 bankTransfer()라는 메서드로 정의되고, 계좌 내에 입금과 출금은 deposit() - 입금, withdraw() - 출금 이라는 메서드로 정의된다고 가정한다. 

- deposit()과 withdraw()는 각자 고유하게 데이터베이스와 커넥션을 맺고 작업을 처리한다. 이 떄, 문제는 withdraw()는 정상적으로 처리되었는데, deposit()에서는 예외가 발생하는 경우이다. 이미 하나의 계좌에서는 돈이 빠져나갔지만, 상대방의 계좌에는 돈이 입금되지 않은 상황이 발생할 수 있다.

 

- '트랜잭션으로 관리하다' 혹은 '트랜잭션으로 묶는다'는 표현은 프로그래밍에서는 'AND' 연산과 유사하다.

- 영속 계층에서 withdraw()와 deposit()은 각각 데이터베이스와 연결을 맺고 처리하는데 하나의 트랜잭션으로 처리해야할 경우에는 한쪽이 잘못되는 경우에 이미 성공한 작업까지 다시 원상태로 복구되어야 한다. 별도의 패턴이나 프레임워크를 사용하지 않는 순수하게 JDBC를 이용하는 코드라면 withdraw()와 deposit()의 내부는 Connection을 맺고 처리하도록 작성된다. 

 

 

- withdraw()와 deposit()이 위와 같이 고유하게 연결을 맺고 처리되는 구조라면 bankTransfer()를 작성할 때는 어느 한쪽이 실패할 떄를 염두에 두고 코드를 복잡하게 만들어야 한다. 스프링은 이러한 트랜잭션 처리를 간단히 XML 설정을 이용하거나, 어노테이션 처리만으로 가능하다.

 

 

✓ Transaction설정

 1) xml을 이용하는 경우

root-context.xml - Namespaces

 

bean 객체 등록

 

2) Java 설정을 이용한 경우

root-context.xml - Source
'aspectj-autoproxy'에 대한 설정을 대신한다.

 

<bean>설정을 대신한다.