231018 TIL #219 AOP

김춘복·2023년 10월 18일
0

TIL : Today I Learned

목록 보기
219/571

Today I Learned

오늘은 Filter, Interceptor에 이어 AOP에 대해 알아봤다.


AOP

  • AOP: Aspect Oriented Programming. 관점 지향 프로그래밍.
    OOP의 모듈성을 더욱 향상시키는 방법이다.
    비즈니스 로직을 기준으로 핵심 관점(비즈니스 로직) / 부가 관점(공통 모듈)으로 나누어서 보고 그 관점을 기준으로 각각을 모듈화 한다.
    부가기능을 Aspect로 모듈화하고 핵심기능에서 분리해 필요한 시점에 비즈니스 로직에 삽입해 재사용하는 것이 AOP의 취지다.

  • AOP는 스프링 Context에서 관리되고, Interceptor 적용 후에 실행된다.

  • Filter, Interceptor와 다르게 URL 패턴이 아닌 주소, 파라미터, 어노테이션, 메서드, 컨트롤러 등 Pointcut이 지원하는 다양한 방식으로 호출위치를 지정할 수 있다.
    그리고 메서드 전후 시점에 자유롭게 설정할 수 있다.

  • Filter와 Interceptor는 HttpServletRequest, HttpServletResponse를 파라미터로 사용한다.
    AOP는 JoinPoint나 ProceedingJoinPoint 등을 활용해서 호출한다.

  • AOP에 대한 자세한 정리는 Spring 심화 #7을 참고.

주 용도

Pointcut을 사용하기 때문에 Filter와 Interceptor보다 구체적이고 세세하게 부가기능을 다룰 수 있다.

  • 세밀한 딘위의 로깅과 보안사항
  • 성능 모니터링(메서드 실행시간 측정)
  • 전달된 파라미터 조사
  • return되는 data 조사 및 변경
  • 예외처리(@ControllerAdvice가 AOP로 구현됨)
  • 트랜잭션 관리(@Transactional이 AOP로 구현됨)

구현 예시

글쓰기 시, admin 계정만 controller의 processtime을 측정하여 로깅하는 로직을 aop로 구현했다. 메서드의 parameter인 userdetails를 aop내에서 활용하여 admin 여부를 check했다. 포인트컷이 @Around로 지정되어 컨트롤러 전/후로 동작한다.

@Aspect
@Component
@Slf4j
public class ProcessTimeAop {

  /*
  Admin 계정으로 글을 작성할 때 processTime을 측정
  writePost 메서드의 2번째 파라미터인 UserDetails를 활용해 admin 유저 여부 check
   */
  @Around("execution(public * com.example.choonb.domain.post.controller.PostController.writePost(..)) && args(.., userDetails))")
  public Object checkProcessTime(ProceedingJoinPoint joinPoint, UserDetailsImpl userDetails) throws Throwable {
    boolean isAdmin = userDetails.getAuthorities().stream()
        .anyMatch(authority -> authority.getAuthority().equals("ROLE_ADMIN"));

    if (!isAdmin) return joinPoint.proceed();

    long startTime = System.currentTimeMillis();

    try {
      return joinPoint.proceed();
    } finally {
      long processTime = System.currentTimeMillis() - startTime;
      log.info("[ProcessTime] : " + processTime + "ms");
    }
  }

}
profile
Backend Dev / Data Engineer

0개의 댓글