Server/Spring

Spring - 트랜잭션 처리

JaeHoney 2020. 9. 29. 18:59

 

스프링에서의 트랜잭션 처리

트랜젝션(Transaction)두 개 이상의 쿼리를 한 작업으로 실행해야 할 때 그 작업의 단위트랜젝션입니다. 트랜젝션의 쿼리가 모두 성공해서 DB에 반영하는 것을 commit이라고 하고, 취소하고 되돌리는 것을 rollback이라 합니다.

 

JDBC API로 트랜젝션을 처리하려면 Connection 클래스의 setAutoCommit(false)로 자동 커밋을 비활성화하고 수동 commit()과 rollback() 메서드를 이용해서 트랜젝션을 커밋하거나 롤백해야 합니다. 즉, 프로그램이 커밋을 못하게 막고 트랜잭션에 있는 쿼리들을 전부 수행후 성공하면(try의 끝) 커밋 하고 실패하면(catch) 롤백합니다. 하지만 위와 같이 작성하면 개발자가 실수했을 경우 문제가 발생할 우려가 있으며, 구조적으로 불필요한 코드가 반복됩니다.

 

스프링이 제공하는 또 다른 장점은 트랜젝션 관리가 쉽다는 것입니다. 스프링을 사용한다면 아래와 같이 트랜젝션을 적용하고 싶은 메서드에 @Transactional 애노테이션을 붙이기만 하면 됩니다. 커밋과 롤백 스프링이 알아서 처리하므로 개발자는 핵심 코드만 집중해서 작성하면 됩니다.

@Transactional
public void remitMoney(String reciver, String sender, long money){
    aFunction();
    bFunction();
}

스프링은 @Transactional 애노테이션이 붙은 remitMoney() 메서드를 하나의 트랜젝션으로 실행합니다. 즉, aFunction()과 bFunction()을 하나의 트랜젝션에 포함합니다.

 

스프링 프록시를 이용해서 트랜젝션을 처리합니다. 프록시는 여러 빈에 공통으로 적용되는 기능을 구현하는 패턴이고 트랜잭션도 공통 기능이기 때문입니다. 

 

설정

스프링에서 @Transactional 애노테이션이 동작하려면 아래와 같은 설정을 추가해야 합니다. 

@EnableTransactionManagement
public class AppCtx {

	@Bean
	public PlatformTransactionManager transactionManager() {
		return new DataSourceTransactionManager(dataSource());
	}
}

@EnableTransactionManagement 애노테이션@Transactional 애노테이션을 활성화합니다. 

 

PlatformTransactionManager는 스프링이 제공하는 트랜젝션 매니저 인터페이스입니다. 트랜잭션 연동에 사용할 DataSource를 지정합니다.

 

@Transactional

별도의 추가 설정을 하지 않으면 트랜젝션이 롤백되는 기준RuntimeException또는 Error의 발생입니다.

 

JdbcTemplate을 사용할 때의 DataAccessException은 RuntimeException을 상속합니다. 따라서 JdbcTemplate의 기능 실행 중 Exception이 발생해도 프록시는 트랜젝션을 rollback합니다.

 

하지만 SQLException은 RuntimeException을 상속하고 있지 않습니다. 만약 이 때도 트랜젝션을 rollback하려면

@Transactional(rollbackFor = SQLException.class)

@Transactional의 rollbackFor 속성을 사용하면 됩니다.

@Transactional(rollbackFor = {AException.class, BException.class})

배열을 사용할 수도 있습니다.

@Transactional(noRollbackFor = AException.class)

반대로 noRollbackFor은 롤백시키지 않고 커밋해도 괜찮은 익셉션을 지정합니다.

 

@Transactional 애노테이션에서 많이 쓰는 속성은 아래에 있습니다.

  • isolation - 트랜젝션 격리 레벨
  • value - PlatformTransactionManager 빈의 이름 지정
  • progation - 트랜젝션 전파 규칙
  • readOnly - 해당 트랜젝션을 읽기 전용으로 처리
  • timeout - 트랜젝션 제한 시간, 시간 내 메소드 수행이 되지 않으면 rollback함

*주의 - isolation, progation은 상업할 프로젝트라면 특히 더 중요합니다. 잘 알아보고 사용합시다.