DB 작업을 하나의 단위로 묶어 성공하면 commit, 실패하면 rollback하는 기능
Spring Transaction은 AOP 기반이다
-> 메서드 실행 전/후에 트랜젝션 관련 처리를 자동으로 끼워 넣음
관점 지향 프로그래밍
코드의 공통 관심사를 분리해서 핵심 비즈니스 로직과 부가 로직(로그, 보안, 트랜젝션 등)을 나누는 프로그래밍 기법
여러 곳에서 반복되는 부가 기능을 빼서 한곳에서 따로 처리하는 방법.
핵심 로직은 그대로 두고, 공통되는 관심사(Aspect)를 따로 분리해서 깔끔한 코드를 만들 수 있게 한다
분리 전 코드- 결제 + 로깅
public void pay() {
System.out.println("[로그] 결제 시작");
// 결제 처리 로직
System.out.println("[로그] 결제 완료");
}
분리 후 코드- 결제/로깅
public void pay() {
// 결제 처리 로직만 집중
}
@Aspect
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore() {
System.out.println("[Log] 메서드 실행 전");
}
@After("execution(* com.example.service.*.*(..))")
public void logAfter() {
System.out.println("[Log] 메서드 실행 후");
}
}
pay()는 결제 로직만 담당하고, 로그는 따로 빼서 LogAspect 클래스에서 자동으로 실행되게 설정.
| 용어 | 의미 |
|---|---|
| Aspect | 공통 기능(로그, 트랜젝션 등)을 정의한 모듈 |
| Advice | 언제 실행할지를 정의(before, after, around 등) |
| JoinPoint | Advice가 끼어들 수 있는 지점(메서드 실행 지점 등) |
| Pointcut | 어떤 JoinPoint에 Advice를 적용할지 지정 |
| Weaving | Advice를 실제 코드에 적용하는 과정(런타임 또는 컴파일 타임 등) |
@Transacntional)@LogExecution)@Secured)-> 비즈니스 로직과 상관없는 공통 관심사 분리 시 사용
간단히
@Transactional)자세히
프록시 객체가 메서드를 가로챔
@Transactional이 붙은 메서드를 프록시로 감싼다
@Service
public class OrderService {
@Transactional
public void placeOrder() {
// 실제 메서드 내용
}
}
- `OrderService` 내부적으로 프록시가 생성되어 실행 흐름을 통제함
트랜젝션 시작(TransactionManager 사용)
TransanctionManager를 통해 DB 커넥션을 얻고, 트랜젝션을 시작함connection.setAutoCommit(false); // JDBC
비즈니스 로직 실행
정상 종료 Or 예외 발생 상황 판단
4-1. 예외가 없을 시 -> commit() 실행, 변경 사항 DB 반영
4-2. 예외 발생 시 -> rollback() 실행, 이전 상태로 되돌림
RuntimeException이나 Error만 롤백함(Checked Exception은 자동 롤백하지 않음, 필요시 rollbackFor 옵션 설정)@Transactional(rollbackFor = Exception.class)
Checked Exception
컴파일 시점에 반드시 처리해야 하는 예외. IOException, SQLException 등
반드시 try-catch하거나, throws를 선언해야 함
주로 외부 시스템과의 통신, 입출력, DB 작업 등에서 발생
Throwable
├── Error (JVM 관련, OutOfMemory 등 → 거의 신경 안 씀)
└── Exception
├── Checked Exception (IOException, SQLException 등)
└── RuntimeException (NullPointerException, IllegalArgumentException 등)
트랜젝션 종료 및 자원 정리
자기 자신을 호출하는 경우
this.transactionMethod()는 프록시를 타지 않아서 트랜젝션 안 먹음.public 메서드에만 적용됨
프록시 미적용 시 주의
@Component 누락)예외 처리 try-catch 후 무시할 경우