임빈영 2021. 9. 23. 18:04

AOP

AOP의 필요성

 

 - 모든 메서드의 호출 시간을 측정하고 싶은 경우를 생각해본다.

 - 해결 방법은 위 사진과 같이 각 계층마다 시간을 측정하는 로직을 작성하는 방법이 있다.

 - 이때, 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 코드가 복잡해지고 유지보수가 어려워진다는 문제점이 발생한다.

 - 핵심 관심 사항(핵심 비즈니스 로직)과 공통 관심 사항(시간을 측정하는 로직)을 분리함으로써 이러한 문제점을 해결할 수 있다.

 

AOP를 통한 해결

 

 - 위 그림과 같이 핵심 관심 사항(핵심 비즈니스 로직)과 공통 관심 사항(시간을 측정하는 로직)을 분리한다.

 - 시간을 측정하는 로직을 공통 로직으로 만든 후 원하는 적용 대상을 선택해 준다.

 - 이와 같이 공통으로 처리해야 하는 기능들을 별도로 분리함으로써, 핵심 관심 사항을 깔끔하게 유지할 수 있다.

 - 또한, 변경이 필요하다면 공통으로 사용되는 로직만 변경해주면 된다.

 

AOP의 동작 과정

 

 - 위 사진은 AOP를 적용하기 전 각 계층들의 호출 방식이다.

 - 각 클래스들은 Controller, Service, Repository 순으로 차례대로 호출된다.

 

 

 - 위 사진은 AOP를 적용한 후의 각 클래스들의 호출 방식이다.

 - 프록시를 생성하여 프록시를 먼저 호출한 후 프록시가 끝나고 나서 비로소 타겟이 호출되는 방식이다.

 - 프록시란 타겟을 감싸서 호출을 대신 받는 Wrapping Object이다.

 

AOP 적용
@Component
@Aspect
public class TimeTraceAop {

    @Around("execution(* com.example.springboot..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();

        System.out.println("START : " + joinPoint.toString());

        try {
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();

            long timeMs = finish - start;

            System.out.println("END : " + joinPoint.toString() + " " + timeMs + "ms");
        }
    }
}

 - "@Around" 애너테이션을 통해 타게팅할 범위를 설정해준다. 위 코드에서는 springboot 패키지 내부 전체를 대상으로 타게팅을 한 것이다.

 - joinPoint.proceed() 메서드를 이용하여, AOP가 적용된 다음 타겟을 호출함으로써 시간 측정을 한다.


 

GitHub - qlsdud0604/spring-boot-basic: 스프링 부트의 기본적인 작동원리를 학습하기 위한 프로젝트

스프링 부트의 기본적인 작동원리를 학습하기 위한 프로젝트. Contribute to qlsdud0604/spring-boot-basic development by creating an account on GitHub.

github.com

 

728x90