JAVA SpringBoot의 핵심기능이라고 하면 DI와 AOP를 말한다. 그 중 AOP는 공부할때 많은 어려움이 있다고 익히 들었기에 내가 공부하고 이해한 내용을 정리해보려 한다.
AOP(Aspect Oriented Programming) : 관점 지향 프로그래밍
Cross-Cutting concerns : 횡단 관심사
AOP를 직역하면 관점(Aspect) 지향(Oriented) 프로그래밍이 된다. 다른 말로는 횡단 관심사라고도 명칭하는데 이는 아래 그림과 같이 Customer Service, Sales, Ware House 모듈이 있을때, 이 모듈들이 공통으로 사용하는 공통 관심사를 의미한다. 즉 특정 모듈의 기능과 상관없이 다수의 모듈이 필요로하는 기능을 의미한다.
AOP기술은 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화 하겠다는 의미이다. 여기서 핵심적인 관점은 적용하고자 하는 핵심 비지니스 로직이 되고, 부가적인 관점은 핵심 로직을 실행하기 위해서 행해지는 "데이터베이서 연결", "로깅," "파일 입출력" 같은 것을 예로 들 수 있다.
아래 그림처럼 하나의 모듈을 구성할때 반복적으로 사용되는 부분을 하나의 Aspect로 모듈화하고 핵심적인 비지니스 로직에서 분리하여 재사용하겠다는 것이 AOP의 취지이다. 이는 자주 사용되는 Aspect의 재사용이 가능하며, 핵심기능에 좀 더 집중이 가능하다.
아래의 경우 왼쪽 코드와 같이 모든 매소드에서 같은 출력문이 있는 것을 확인할 수 있다. 이러한 경우에 왼쪽 처럼 추가되는 부분의 내용을 하나의 객체로 분리하면 효율적이다.
모든 메서드의 구조가 같은 형태가 아니기 때문에 코드를 자동으로 추가하는 매서드는 대상 매서드의 시작, 끝 부분에만 추가가 가능하다. 여기서 시작 부분에 추가하는 경우를 "Before Advice"
끝 부분에 추가하는 경우를 "After Advice"
라고 하며 두 부분 모두에 추가하는 경우를 "Around Advice"
라고 한다.
advice의 종류에는 크게 Around, Before, After 세 종류가있고, After advice이 returning과 thorowing으로 나누어진다. 이 두 종류는 try - catch
과 유사하게 동작한다.
@AOP을 사용하기 위해서는 의존성을 추가해야 한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
애너테이션을 붙여 해당 클래스가 부가기능(advice)를 기능하는 클래스임을 명시하고 @Component
를 붙여 스프링 객체(Bean)으로 등록한다.
@Component
@Aspect
class LoggingAdvice{
@Around("execution(* com.ch3.aop.MyMath.add*(..))")
public Object methodClassLog(ProceedingJoinPoint pjp) throws Throwable{
long start = System.currentTimeMillis();
System.out.println("<<[start]"+pjp.getSignature().getName() + Arrays.toString(pjp.getArgs()));
Object result = pjp.proceed();
System.out.println("result: "+ result);
System.out.println("[end]>>" + (System.currentTimeMillis() - start) + "ms");
return result;
}
}
> execution( 생략 * com.ch3.aop.MyMath.add*(..))
> execution(접근제어자 반환타입 패키지명 클래스명.메서드명(매개변수 목록))