[Spring Plus] Level 1-3 요구사항 반영

2024. 11. 12. 17:37내일배움캠프/Spring Plus

 'Level 1-3' 의 요구사항을 반영한 내용을 기록한 포스팅이다. 어떠한 생각과 과정을 통해 요구사항을 반영했는지 알 수 있도록 작성해 보았다.

 

0. 요구사항

 AOP 가 원래 의도와 다르게 잘못 동작하고 있다. 'UserAdminController' 클래스의 'changeUserRole()' 수행전 'AdminAccessLoggingAspect' 클래스의 'logAfterChangeUserRole()' 이 동작하도록 코드를 수정해야 한다.

 

 

1. 문제 원인 파악

 현재 프로젝트의 'org.example.expert.aop.AdminAccessLoggingAspect' 클래스는 아래와 같다.

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class AdminAccessLoggingAspect {

    private final HttpServletRequest request;

    @After("execution(* org.example.expert.domain.user.controller.UserController.getUser(..))")
    public void logAfterChangeUserRole(JoinPoint joinPoint) {
        String userId = String.valueOf(request.getAttribute("userId"));
        String requestUrl = request.getRequestURI();
        LocalDateTime requestTime = LocalDateTime.now();

        log.info("Admin Access Log - User ID: {}, Request Time: {}, Request URL: {}, Method: {}",
                userId, requestTime, requestUrl, joinPoint.getSignature().getName());
    }
}

 

요구사항에 따르면 해당 클레스에 작성된 'logAfterChanageUserRole()' 은 지정된 메서드(=타겟) 수행전에 수행되어야 한다고 명시되어있다. 하지만 현재 메서드명부터가 "사용자 역할을 변경하고 로그를 남기는~" 을 나타내고 있기에 메서드명 또한 변경해야 할 것으로 보인다.

 

물론 메서드명보다 근본적인 문제는 'logAfterChangeUserRole()' 에 지정된 '@After' 이다. 해당 어노테이션에 대한 설명을 라이브러리 docs 에서 확인하면 아래와 같다.

라이브러리 docs - @After

 

상당히 심플한 설명이다. 설명에 등장하는 'advice' 는 타겟에 제공할 부가기능을 담은 모듈이라고 보았고, 아래와 같은 내용으로 해석할 수 있었다.

타겟 동작(수행) 이후 adivce 수행

 

즉, 의도한 바는 ' changeUserRole()' 수행 전에 해당 모듈이 동작(수행)되는 것 이었는데 '@After' 를 사용해 의도한 반대로 동작하게 된 것으로 보인다.

 

그리고 타겟 지정도 잘못 작성된 것으로 보인다. 분명 'UserAdminController' 클래스의 'changeUserRole()' 수행 전 모듈이 동작해야 함에도 'UserController' 클래스의 'getUser()' 를 타겟으로 지정하도록 작성되어 있다.

@After("execution(* org.example.expert.domain.user.controller.UserController.getUser(..))")

 

위에서 말한 3가지(1가지는 동작과 관련 없음)를 본래 의도에 맞게 수정한다면 요구사항에 따라 AOP 가 정상작동 할 거라 생각된다.

 

 

2. 문제 해결

 우선 동작과는 관련 없으나 추후 다른 개발자에게 혼동을 주지 않도록 메서드명을 아래와 같이 수정하였으며, '@After' 가 아닌 '@Before' 를 사용하고 모듈의 타겟을 'UserAdminController' 클래스의 'changeUserRole()' 으로 지정하였다.

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class AdminAccessLoggingAspect {
    ...

    @Before("execution(* org.example.expert.domain.user.controller.UserAdminController.changeUserRole(..))")
    public void logBeforeChangeUserRole(JoinPoint joinPoint) {
        ...
    }
}

 

위와 같이 코드를 수정한 이후 Postman 을 통해 API 요청(회원 역할 변경)을 아래와 같이 테스트 했다.

회원 역할 변경 요청
회원 역할 변경 요청시 실행창의 로그 및 쿼리

 

API 요청은 정상적으로 수행되었으며 실행창의 내용을 통해 'logBeforeChangeUserRole()' 모듈이 'changeUserRole()' 수행 전 잘 동작해 로그를 남겼음을 확인할 수 있었다.

 

물론 정확하게 'changeUserRole()' 수행전 로그가 작성된 것인지 확인하려면 해당 메서드에도 로그를 남기는 로직을 작성해 확인해야 하겠지만, 회원 역할 변경에 대한 쿼리가 로그 이후 작성된 것을 보면 충분히 'changeUserRole()' 수행전 'logBeforeChangeUserRole()' 이 동작했다 볼 수 있을 것 같다.