[스프링] 프록시 기반 AOP(Aspect Oriented Programming) 정리
Spring Boot

[스프링] 프록시 기반 AOP(Aspect Oriented Programming) 정리

728x90

AOP (Aspect Oriented Programming)

AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불린다. 관점 지향은 쉽게 말해 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것이다. 여기서 모듈화란 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것을 말한다. 

 

AOP 주요 개념

개념 설명
Aspect 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화 한다.
Target Aspect를 적용하는 곳 (클래스, 메소드,...)
Advice 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체
JoinPoint Advice가 적용될 위치, 끼어들 수 있는 지점이다. 메소드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용 가능하다.
PointCut JoinPoint의 상세한 스펙을 정의한 것이다. 'A란 메소드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있다.

 

 

AOP 특징

1. 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가 기능을 추가하기 위해서이다.

2. 스프링 빈에만 AOP를 적용 가능하다.

3. 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체들 간 관계 복잡도 증가 등)에 대한 해결책을 지원하는 것이 목적이다.

 

 

AOP 예시

이번 글에서는 특정 메소드의 실행 시간이 얼마나 걸리는지 체크해주는 어노테이션을 구현해볼 것이다. 결론부터 말하면 @LogExecutionTime 어노테이션을 붙이면 로그에 실행시간이 출력되게끔 만들 것이다.

> LogExecutionTime

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD) // 메소드에서 어노테이션을 적용할 수 있게끔 설정한다.
@Retention(RetentionPolicy.RUNTIME) // 런타임동안 적용되게끔 한다
public @interface LogExecutionTime {

}

 

> LogAspect

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component // Bean으로 등록
@Aspect 
public class LogAspect {
    Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Around("@annotation(LogExecutionTime)") // LogExectionTime 어노테이션 주변에서 실행한다.
    public Object LogExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed(); // 어노테이션이 붙어 있는 메소드가 joinPoint, 메소드를 실행시킨다.
        long end = System.currentTimeMillis();

        logger.info("실행 시간 : " + (end - start));
        return proceed; // 실행된 메소드를 리턴해준다.
    }
}

 

> HelloController

import com.leveloper.chacha.springbootchacha.aop.LogExecutionTime;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    @LogExecutionTime // 앞서 만든 LogExecutionTime 어노테이션 추가
    public String hello(){
        return "hello";
    }
}

 

애플리케이션을 실행시켜 "/hello" 위치로 접속해보면 로그에 실행 시간이 찍히는 것을 확인할 수 있다.

 

 

마무리

이번에는 프록시 기반의 AOP를 활용하여 공통 로직을 모듈화 하는 방법에 대해 알아보았다. AOP는 위의 방법 이외에도 다양한 방법으로 활용할 수 있다. 좀 더 자세한 내용은 https://sjh836.tistory.com/157를 참고하자.

728x90