트랜잭션(Transaction) 이란?
· 데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위를 뜻한다.
· 스프링은 PlatformTransactionManager라는 인터페이스를 통해 트랜잭션을 추상화한다.
PlatformTransactionManager 인터페이스
package org.springframework.transaction;
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
· 스프링은 트랜잭션을 추상화해 제공할 뿐만 아니라, 실무에서 주로 사용하는 데이터 접근 기술에 대한 트랜잭션 매니저의 구현체도 제공한다. 개발자는 필요한 구현체를 스프링 빈으로 등록하고 주입 받아 사용하면 된다.
· 스프링 부트는 어떤 데이터 접근 기술을 사용하는지를 자동으로 인식해서 적절한 트랜잭션 매니저를 선택해 스프링 빈으로 등록해준다.
스프링 트랜잭션 사용 방식
PlatformTransactionManager를 사용하는 2가지 방법
· 선언적 트랜잭션 관리
· 프로그래밍 방식 트랜잭션 관리
☞ 선언적 트랜잭션 관리 (Declarative Transaction Management)
· @Transactional 애노테이션 하나만 선언해 매우 편리하게 트랜잭션을 적용한다.
· 선언적 트랜잭션 관리는 과거 XML에 설정하기도 했다.
· 이름 그대로 어딘가에 선언하기만 하면 트랜잭션이 적용되는 방식이다.
· 실무에서는 대부분 선언적 트랜잭션 관리를 사용한다.
☞ 프로그래밍 방식 트랜잭션 관리 (Programmatic Transaction Management)
· 트랜잭션 매니저 또는 트랜잭션 템플릿 등을 사용해 트랜잭션 관련 코드를 직접 작성한다.
선언적 트랜잭션과 AOP
@Transactional을 통한 선언적 트랜잭션 관리 방식을 사용하게 되면 기본적으로 프록시 방식의 AOP가 적용된다.
프록시 도입 전
//트랜잭션 시작
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
//비즈니스 로직
bizLogic(fromId, toId, money);
transactionManager.commit(status);//성공시 커밋
} catch (Exception e) {
transactionManager.rollback(status);//실패시 롤백
throw new IllegalStateException(e);
}
프록시 도입 후
public class TransactionProxy {
private MemberService target;
public void logic() {
//트랜잭션 시작
TransactionStatus status = transactionManager.getTransaction(..);
try {
//실제 대상 호출 target.logic();
transactionManager.commit(status);//성공시 커밋
}catch (Exception e) {
transactionManager.rollback(status);//실패시 롤백
throw new IllegalStateException(e);
}
}
}
public class Service {
public void logic() {
//트랜잭션 관련 코드 제거, 순수 비즈니스 로직만 남음
bizLogic(fromId, toId, money);
}
}
· 프록시 도입 전: 서비스에 비즈니스 로직과 트랜잭션 처리 로직이 함께 섞여있다.
· 프록시 도입 후: 트랜잭션 프록시가 트랜잭션 처리 로직을 모두 가져가고, 서비스 계층에는 순수 비즈니스 로직만 남길 수 있다.
프록시 도입 후 전체 과정
· 스프링 부트를 사용하면 트랜잭션 AOP를 처리하기 위해 필요한 스프링 빈들도 자동으로 등록해준다.
· 스프링은 트랜잭션 처리가 필요한 곳에 @Transactional 애노테이션만 붙여주면, 트랜잭션 AOP는 이 애노테이션을 인식해 트랜잭션을 처리하는 프록시를 적용해준다.
트랜잭션 적용 위치
· 스프링에서 우선순위는 항상 더 구체적이고 자세한 것이 높은 우선순위를 가진다.
· @Transactional == @Transactional(readOnly = false)
· 스프링 @Transactional은 두 가지 규칙이 있다.
1. 우선순위 규칙
2. 클래스에 적용하면 메서드는 자동 적용
예외와 트랜잭션 Commit, Rollback
· 예외 발생시 스프링 트랜잭션 AOP는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다.
· 언체크 예외인 RuntimeException, Error와 그 하위 예외가 발생하면 트랜잭션을 롤백한다.
· 체크 예외인 Exception과 그 하위 예외가 발생하면 트랜잭션을 커밋한다.
· 정상 응답하면 트랜잭션을 커밋한다.
· 체크 예외: 비즈니스 의미가 있을 때 사용 (commit)
· 언체크 예외: 복구 불가능한 예외 (rollback)
'Spring Study > DataBase' 카테고리의 다른 글
[DataBase] JPA / Spring Data JPA (0) | 2023.10.03 |
---|---|
[DataBase] 데이터 접근 기술 - 테스트 (0) | 2023.09.25 |
[DataBase] 데이터 접근 기술 (0) | 2023.09.22 |
[DataBase] 예외 처리 (0) | 2023.09.21 |
[DataBase] 자바 예외 (Exception) (0) | 2023.09.20 |
댓글