Spring/JPA + Security

[Spring] AOP 처리하기 - 유효성 검사 자동화

pyogowoon 2023. 1. 15. 15:55

AOP란 Aspect Oriented programming 으로

 

AOP의 정의

 

AOP는 한국에서 관점지향 프로그래밍, 또는 상황중심 프로그래밍으로 번역되는 하나의 프로그래밍 방법론이다다.

AOP는 절차지향이나 객체지향 프로그래밍처럼 그 자체로 하나의 프로그램을 형성할 수 있는 건 아니다.

하지만 AOP는 객체지향 코드 위에서 이루어지며 객체지향을 보조하는 역할을 한다고 보시면 된다.

 

handler의 aop 패키지를 하나 만들고,

 

 

@Component //RestController, Service 모든 것들이 component를 상속해서 만들어져있음
@Aspect
public class ValidationAdvice {

    @Around("execution(* com.pyo.pyostagram.web.api.*Controller.*(..))")
    public Object apiAdivice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof BindingResult) {

                BindingResult bindingResult = (BindingResult) arg;
                if (bindingResult.hasErrors()) {
                    Map<String, String> errorMap = new HashMap<>();

                    for (FieldError error : bindingResult.getFieldErrors()) {
                        errorMap.put(error.getField(), error.getDefaultMessage());
                    }
                    throw new CustomValidationApiException("유효성 검사 실패함", errorMap);
                }
            }
        }

        return proceedingJoinPoint.proceed();
    }

    @Around("execution(* com.pyo.pyostagram.web.*Controller.*(..))")
    public Object advice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof BindingResult) {

                BindingResult bindingResult = (BindingResult) arg;
                if (bindingResult.hasErrors()) {

                    Map<String, String> errorMap = new HashMap<>();

                    for (FieldError error : bindingResult.getFieldErrors()) {
                        errorMap.put(error.getField(), error.getDefaultMessage());
                    }
                    throw new CustomValidationException("유효성검사 실패", errorMap);
                }
            }
        }


        return proceedingJoinPoint.proceed();
    }


}

 

 

 

aop 처리

@Aspect  -- aop처리할수있는 핸들러가 됨

 

@Around("execution(* com.pyo.pyostagram.web.*Controller.*(..))")

 

첫번째 * :어떤메서드로 할래? 예를들면 protected , public 메서드로할래 이런뜻
두번째 * : *Controller  ~Controller로 끝나는 모든 애들
세번째 *(..) :  모든 메서드 , 뒤에 (..)는 모든 파라메터를 허용한다는 뜻


proceedingJoinPoint 란? 
 해당 메서드의 모든 정보에 접근할 수 있는 파라메터(내부까지 접근가능)

return proceedingJoinPoint.proceed();  :  해당 메서드로 돌아가라

즉 어디서 어떤 메소드가 호출되면 가장 먼저 ProceedingJoinPoint가 실행됨, 로직을 실행하고
다시 메서드로 돌아감.
 

이제 테스트를 해볼것이다.

 

모든 controller에 있는 if문을 사용한 bindingResult 는 모두 지워준다.

 

이제 백엔드에서의 유효성 검사는

  메서드의 매개변수에 bindingResult 만 있다면 알아서 aop가 처리해준다.

 테스트를 위해

 

//
// if (data.content === "") {
//    alert("댓글을 작성해주세요.");
//    return;
// }

 저번시간 처럼 프론트 유효성검사를 잠시 주석처리해주고 실행해보면

 

 

 

bindingResult 관련 if문을 모두 지웠음에도 불구하고

 custm Exception 이 잘 작동한다.