Spring AOP

bp.chys·2020년 5월 17일
0

Spring Framework

목록 보기
5/15

AOP (Aspect Oriented Programming)

  • 핵심기능(비즈니스 로직)과 공통기능(인프라 로직)의 구현을 분리할 수 있다.
  • 공통기능이란 여러 객체에 공통적으로 적용할 수 있는 기능으로 애플리케이션의 여러 지점에 걸쳐있는 기능이다.
  • 공통기능을 모듈화함으로써 재사용성을 높여주는 프로그래밍 기법이라고 할 수 있다.
  • 대표적으로 인증, 트랜잭션 관리, 로깅 등과 같은 인프라 로직을 AOP로 처리한다.
  • 스프링은 프록시 기반 AOP를 지원한다.
  • AspectJ가 Spring AOP보다 더 성능이 좋고, 모든 pointcuts 모든 domain objects에 대해서도 적용이 가능하다는 특징이 있지만, 별도의 컴파일러가 필요하고 구현이 복잡하다. 후자는 메서드에 대해서만 AOP기능을 제공한다.

동작 방식 (feat.프록시)

  • 프록시 객체란 핵심 기능의 실행은 다른 객체에 위임하고, 부가적인 기능을 제공하는 객체
  • 스프링은 런타임 시점에 대상 객체를 감싸는 프록시를 만든다.

  • 프록시는 대상 객체에 대한 호출을 가로챈 다음 어드바이스의 부가기능 로직을 수행하고 난 후에 다시 요청을 반환하여 대상 객체의 핵심 기능을 수행한다.
  • 혹은 핵심기능을 먼저 수행할 수 도 있다.
  • 기존 코드를 수정하지 않으면서 코드 중복을 제거할 수 있는 장점이 있다.

AOP 용어 정리

  • Aspect : 어드바이스 + 포인트컷, 싱글톤 객체로 존재한다. ex) transaction management
  • Joint-Point : 어드바이스가 적용될 수 있는 위치를 말한다. ex) method, class etc..
  • Advice : 타겟에 제공할 부가기능을 담고 있는 모듈이다.
  • Pointcut : 어드바이스를 적용할 타겟의 메서드를 선별하는 정규표현식이다. Joint-Point와 비슷한 의미로 사용된다.
  • Target Object : 핵심 기능을 담고 있는 모듈로 부가기능을 부여할 대상이 된다.

Demo) AOP로 로깅적용하기

1. 먼저 로깅을 적용하기 위해서는 configuration에 @EnableAspectAutoProxy 어노테이션을 지정해준다.

@EnableAspectAutoProxy
@SpringBootApplication
public class LogginApplication {

    public static void main(String[] args) {
        SpringApplication.run(LoggingApplication.class, args);
    }
}

2. 로깅을 수행하는 Aspect 빈을 생성한다.

@Component
@Aspect
@Slf4j
class ControllerLoggingAspect {

    @Pointcut("execution(* demo.logging..*Controller.*(..))")
    public void loggerPointCut() {
    }

    @Around("loggerPointCut()")
    public Object methodLogger(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

        log.info("Request Body : {}", getParmas(request));
        return result;
    }

    private static JSONObject getParams(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject();
        Enumeration<String> params = request.getParameterNames();
        while (params.hasMoreElements()) {
            String param = params.nextElement();
            String replaceParam = param.replaceAll("\\\\.", "-");
            jsonObject.put(replaceParam, request.getParameter(param));
        }
        return jsonObject;
    }
}

결론

AOP는 OOP가 미처 해결하지 못한 핵심 기능과 공통기능의 관심사의 분리를 가능하게 해주는 프로그래밍 기법이다. Aspect라는 빈을 만들어서 부가기능과 적용 시점을 정의할 수 있다.

Spring은 런타임 시점에 대상 객체에 대한 프록시 객체를 만들어 대상객체 전/후 요청을 가로채고, Aspect에 정의된 부가기능을 수행한 뒤 요청을 반환하면서 기존의 코드가 수행되게 한다.

스프링 프레임워크가 제공하는 핵심 기능 중 하나인 만큼, 개발의 생산성을 크게 높이고 더욱 모듈화된 코드를 작성할 수 있는 좋은 기법인 것 같다.

profile
하루에 한걸음씩, 꾸준히

0개의 댓글