Java Category/Spring

[Spring 입문] AOP (Aspect Oriented Programming)

ReBugs 2024. 1. 25.

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


AOP가 필요한 상황

몇개의 메서드에 실행시간을 체크해보고싶은 상황이라고 한다면 해당 메서드들의 시작과 끝에 시간을 측정하고 출력하는 코드를 붙여야할 것이다.

다행히 그게 몇개 밖에 되지않는다면 괜찮겠지만 만약 몇십개, 몇백개라면 노가다 작업을 해야할 것이다.

예를 들어, AOP를 적용하지 않고, 각 메서드마다 실행시간을 측정을 해야한다면 아래와 같은 문제점을 만나게 된다.

  • 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
  • 시간을 측정하는 로직은 공통 관심 사항이다.
  • 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.

 

이때 필요한 기술이 바로 AOP이다.

AOP는 공통적인사항(시간측정)을 핵심관심사항과 아래와 같이 분리해준다.

 

AOP 적용 전

 

AOP 적용 후

 

 

AOP 적용

  • AOP: Aspect Oriented Programming
  • 공통 관심 사항(cross-cutting concern), 핵심 관심 사항(core concern) 분리

package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeTraceAop { 
    @Around("execution(* hello.hellospring..*(..))") //적용 범위
    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");
        }
    }
}

컴포넌트 스캔방식으로 스프링 빈으로 등록해주고 @Aspect라는 어노테이션을 붙여준다.

그리고 실행할 함수(execute 메서드)를 작성한다.

시간을 측정해야하기때문에 시작 시간을 측정해준 뒤 try문에서 JointPoint의 proceed 메서드를 실행해준다.

메서드가 끝난 후에 종료 시간을 측정한뒤 종료 시간에서 시작 시간의 차이를 구하여 경과시간을 출력해준다.

execute함수 위에 @Around 어노테이션을 붙여서 어디까지 이 시간측정을 적용할지 범위를 정해줄 수 있다.

여기서는 모든 메서드에 적용하도록 hello.hellospring 의 모든 하위 패키지를 적용시킨 것이다.

 

이로써 AOP를 적용시키기 전에 문제점을 아래와 같이 해결하였다.

  • 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
  • 핵심 관심 사항을 깔끔하게 유지할 수 있다.
  • 변경이 필요하면 이 로직만 변경하면 된다.
  • 원하는 적용 대상을 선택할 수 있다.

 

스프링의 AOP 동작 방식

AOP를 적용하기 전의 의존관계는 아래와 같다.

 

AOP 적용 후의 의존관계는 아래와 같다.

 

실제 스프링 빈들 앞에 proxy 빈을 만들어주고 스프링 컨테이너는 의존성 주입때 proxy빈을 넣어준다.

그러면 실제 빈을 실행할 때도 proxy빈이 수행되고 joinpoint가 각각의 메서드들이 실행될 때 개입해 시간체크를 해주는 방식이다.

여기서 joinpoint의 proceed()가 실행될 때 실제 프록시빈이 수행된다.

댓글