Spring/Transaction

Spring Transaction 이란?

hwanguu 2023. 8. 15. 17:26

Transaction 이란?

만약 데이터베이스의 데이터를 수정하는 도중에 예외가 발생된다면 어떻게 해야 할까? DB의 데이터들은 수정이 되기 전의 상태로 다시 되돌아가져야 하고, 다시 수정 작업이 진행되어야 할 것이다.

이렇듯 여러 작업을 진행하다가 문제가 생겼을 경우 이전 상태로 롤백하기 위해 사용되는 것이 트랜잭션(Transaction) 이다.

트랜잭션은 더 이상 쪼갤 수 없는 최소 작업 단위를 의미한다. 그래서 트랜잭션은 commit으로 성공 하거나 rollback으로 실패 이후 취소되어야 한다. 하지만 모든 트랜잭션이 동일한 것은 아니고 속성에 따라 동작 방식을 다르게 해줄 수 있다. 

예를 들어 1개의 새로운 데이터를 추가하는 와중에 에러가 발생하면 해당 추가 작업은 없었던 것처럼 되돌려진다. 하지만 만약 여러 개의 작업에 대해 롤백을 하려면 어떻게 해야 될까? 여러 개의 작업을 1개의 트랜잭션으로 관리해야 할 것이다.

위에서 설명한 것과 마찬가지로 트랜잭션의 마무리 작업으로는 크게 2가지가 있다.

  • 트랜잭션 커밋: 작업이 마무리 됨
  • 트랜잭션 롤백: 작업을 취소하고 이전의 상태로 돌림

만약 여러 작업이 모두 마무리 되었다면 트랜잭션 커밋을 통해 작업이 마무리되었음을 알려주어 반영해야 하며, 만약 문제가 생겼다면 작업 취소를 위해 트랜잭션 롤백 처리를 해주어야 한다.

 

Spring Transaction

Spring Transaction 이란 SpringFramework 에서 제공하는 Transaction 관리 기술이다.

예를 들면 DB 관련 Transaction을 관리 해주는 기술이라고 할 수 있다.

 

Transaction을 처리하는 방식에는 여러가지가 있다.

- JDBC 트랜잭션

- JPA 트랜잭션

- Hibernate 트랜잭션

- 기타 트랜잭션

 

 

내가 어떤 기술을 사용하고자 하냐에 따라서 트랜잭션 처리 방식도 달라질 것이다. (아래 소스를 참고 하자)

 

JDBC 트랜잭션 코드 예시

public void accountTransfer(String fromId, String toId, int money) throws SQLException {
 Connection con = dataSource.getConnection();
 	try {
 		con.setAutoCommit(false); //트랜잭션 시작
 		//비즈니스 로직
 		bizLogic(con, fromId, toId, money);
 		con.commit(); //성공시 커밋
 	} catch (Exception e) {
 		con.rollback(); //실패시 롤백
 		throw new IllegalStateException(e);
 	} finally {
 	release(con);
 	}
}

 

JPA 트랜잭션 코드 예시

public static void main(String[] args) {
 	//엔티티 매니저 팩토리 생성
 	EntityManagerFactory emf =
	Persistence.createEntityManagerFactory("jpabook");
 	EntityManager em = emf.createEntityManager(); //엔티티 매니저 생성
 	EntityTransaction tx = em.getTransaction(); //트랜잭션 기능 획득
 	try {
 		tx.begin(); //트랜잭션 시작
 		logic(em); //비즈니스 로직
 		tx.commit();//트랜잭션 커밋
 	} catch (Exception e) {
 		tx.rollback(); //트랜잭션 롤백
 	} finally {
 		em.close(); //엔티티 매니저 종료
 	}
 	emf.close(); //엔티티 매니저 팩토리 종료
}

 

위와같이 트랜잭션 처리 방식이 다르기 때문에 어떤 기술을 사용하냐에 따라서 다른 트랜잭션을 사용하게 된다.

 

만약에 JDBC를 사용하다가 JPA로 변경한다면 어떻게 될까?

 

둘의 처리방식이 다르기 때문에 JDBC 기술을 사용하다가 JPA 기술로 변경하게 되면 트랜잭션을 사용하는 코드도 모두 함께 변경해야 한다.

스프링은 이런 문제를 해결하기 위해 트랜잭션 추상화를 제공한다. 트랜잭션을 사용하는 입장에서는 스프링 트랜잭션 추상화를 통해 둘을 동일한 방식으로 사용할 수 있게 되는 것이다.

스프링은 PlatformTransactionManager 라는 인터페이스를 통해 트랜잭션을 추상화한다

 

PlatformTransactionManager 인터페이스

public interface PlatformTransactionManager extends TransactionManager {
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;
            
    void commit(TransactionStatus status) throws TransactionException;
    
    void rollback(TransactionStatus status) throws TransactionException;
}

위 인터페이스 처럼 트랜잭션은 트랜잭션 시작(획득), 커밋, 롤백으로 단순하게 추상화 할 수 있다.

 

 

 

스프링은 트랜잭션을 추상화해서 제공할 뿐만 아니라,

실무에서 주로 사용하는 데이터 접근 기술에 대한 트랜잭션 매니저의 구현체도 제공한다.

우리는 필요한 구현체를 스프링 빈으로 등록하고 주입 받아서 사용하기만 하면 된다.

 

여기에 더해서 스프링 부트는 어떤 데이터 접근 기술을 사용하는지를 자동으로 인식해서 적절한 트랜잭션 매니저를 선택해서 스프링 빈으로 등록해주기 때문에 트랜잭션 매니저를 선택하고 등록하는 과정도 생략할 수 있다.
예를 들어서 JdbcTemplate , MyBatis 를 사용하면 DataSourceTransactionManager(JdbcTransactionManager) 를 스프링 빈으로 등록하고, JPA를 사용하면 JpaTransactionManager 를 스프링 빈으로 등록해준다.

 

 

 

 

References 및 사진 출처

김영한의 스프링 DB 2편 - 데이터 접근 활용 기술