Contents
see ListSpring AOP와 트랜잭션 순서 설정하기
Spring에서 AOP(AspectJ)와 트랜잭션이 동시에 적용될 때 실행 순서를 제어하는 방법입니다. @Order 어노테이션과 Ordered 인터페이스를 활용합니다.
1. 문제 상황
로깅 AOP가 트랜잭션보다 먼저 실행되면 트랜잭션 밖에서 로깅되어 롤백 시 잘못된 로그가 남을 수 있습니다.
// 원하는 순서: 트랜잭션 시작 → 로깅 → 비즈니스 로직 → 로깅 → 트랜잭션 종료
// 잘못된 순서: 로깅 → 트랜잭션 시작 → 비즈니스 로직 → 트랜잭션 종료 → 로깅
2. @Order 어노테이션 사용
@Aspect
@Component
@Order(1) // 숫자가 낮을수록 먼저 실행 (외부)
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
log.info("메서드 시작: {}", pjp.getSignature());
Object result = pjp.proceed();
log.info("메서드 종료: {}", pjp.getSignature());
return result;
}
}
@Aspect
@Component
@Order(2) // LoggingAspect 다음에 실행 (내부)
public class SecurityAspect {
// ...
}
3. 트랜잭션 순서 설정
@Configuration
@EnableTransactionManagement(order = 0) // 가장 먼저 (가장 바깥)
public class TransactionConfig {
// ...
}
// 또는 XML 설정
<tx:annotation-driven order="0"/>
4. 실행 순서 예시
// Order 값: 트랜잭션(0) → 로깅(1) → 보안(2)
트랜잭션 시작 ─┐
로깅 시작 ─┤
보안 체크 ─┤
비즈니스 로직
보안 체크 ─┘
로깅 종료 ─┘
트랜잭션 커밋 ─┘
5. Ordered 인터페이스 구현
@Aspect
@Component
public class LoggingAspect implements Ordered {
@Override
public int getOrder() {
return 1;
}
// ...
}
6. 실전 권장 순서
| Order | Aspect | 용도 |
|---|---|---|
| 0 | Transaction | 트랜잭션 관리 (가장 외부) |
| 1 | Logging | 메서드 진입/종료 로깅 |
| 2 | Security | 권한 검사 |
| 3 | Validation | 입력값 검증 |
| 4 | Caching | 캐시 처리 |
7. 주의사항
- Order 값이 같으면 실행 순서 보장 안 됨
- @Order는 Spring Bean에만 적용
- Lowest값(Integer.MAX_VALUE)이 가장 마지막 실행
- Aspect끼리만 순서 조절, 일반 빈은 별도
8. 디버깅 팁
// 현재 적용된 AOP 순서 확인
@Autowired
private AspectJProxyFactory factory;
// 로그 레벨 설정
logging.level.org.springframework.aop=DEBUG
logging.level.org.springframework.transaction=DEBUG