AOP는 기존 OOP(Object-Oriented-Programming)를 보조하기 위해 등장한 개념으로, 횡단 관심사를 깔끔하게 처리하기 위해 등장하였다.
우리가 만약 기존 코드에 반복적으로 등장하는 부가기능을 추가하고자 한다고 생각해보자. 기존의 OOP는 애플리케이션을 기능을 중심으로 바라보았다. 따라서 코드조각도 기능을 중심으로 나뉘어있고, 반복적으로 등장하는 부가기능을 추가하려면 그 모든 조각들을 하나씩 정성을 들여 수정을 해야한다.
이런 부가기능을 횡단관심사라고 부른다. 우리 애플리케이션의 주요한 핵심기능은 아니지만, 여러 부분에서 반복적으로 등장하는 코드. 이 코드들을 핵심기능에서 분리하고, 한 곳에서 관리하도록 만들어주는 것이 바로 AOP이다.
먼저 이 AOP의 핵심 개념을 짚어보겠다.
Spring AOP의 개념을 이해했으니 우리의 애플리케이션에 이제 한번 적용해보겠다.
implementation 'org.springframework.boot:spring-boot-starter-aop'
build.gradle에 위 코드를 추가하여 AOP기능을 사용할 수 있다.
@Slf4j
@Aspect
public class Aspect {
//dompoo.aop.order 패키지와 그 하위의 모든 클래스
@Pointcut("execution(* dompoo.aop.order..*(..))")
private void allOrder() {} //pointcut signature
//클래스 이름 패턴이 *Service 인 것
@Pointcut("execution(* *..*Service.*(..))")
public void allService() {} //pointcut signature
@Around("allOrder()")
public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[log] {}", joinPoint.getSignature());
return joinPoint.proceed();
}
//dompoo.aop.order 패키지와 그 하위 패키지 이면서 클래스 이름 패턴이 *Service인 것
@Around("allOrder() && allService()")
public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
try {
log.info("[트랜잭션 시작] {}", joinPoint.getSignature());
Object result = joinPoint.proceed();
log.info("[트랜잭션 커밋] {}", joinPoint.getSignature());
return result;
} catch (Exception e) {
log.info("[트랜잭션 롤백] {}", joinPoint.getSignature());
throw e;
} finally {
log.info("[리소스 릴리즈] {}", joinPoint.getSignature());
}
}
}
Aspect 작성법은 간단하다.
이렇게 Aspect를 작성한 후, 컴포넌트 스캔이나 @Import를 해주면 된다.
[log] void dompoo.aop.order.OrderService.orderItem(String)
[트랜잭션 시작] void dompoo.aop.order.OrderService.orderItem(String)
[orderService] 실행
[log] String dompoo.aop.order.OrderRepository.save(String)
[orderRepository] 실행
[트랜잭션 커밋] void dompoo.aop.order.OrderService.orderItem(String)
[리소스 릴리즈] void dompoo.aop.order.OrderService.orderItem(String)
위와 같이 Aspect가 잘 적용된 것을 볼 수 있다.
이렇게 성공적으로 AOP를 사용하여 우리의 비즈니스 로직에서부터 횡단 관심사를 성공적으로 분리하였고, 관리와 수정하기에도 매우 편리해졌다. Spring AOP는 그 내용이 방대하며 특히 AspectJ Pointcut문법을 이용하면 어노테이션 단위로 Advice를 적용하는 일도 가능하다. 다음 글에서 좀 더 깊은 사용법과 프록시 기술의 한계를 짚어보고자 한다.