Springあるある

원하는 기능을 Annotation을 만들어서 활용하기(Feat. ArgumentResolver,Login, @Login)

JIN_YOUNG _KIM 2025. 1. 17. 15:22

우리는 아래의 코드와 같이 @Login 애노테이션이 붙어 있으면 해당 회원(Member)가 로그인된 회원인지 아닌 지를 

판단한 후, 컨트롤러 매개변수인 Member member에 값을 매핑하는 기능을 만들고 싶다. 

이때 사용되는 스프링 인터페이스가 바로 ArgumentResolver이다. 

@Slf4j
@Controller
@RequiredArgsConstructor
public class HomeController {

   
    @GetMapping("/")
    public String homeLoginV3SpringArgumentResolver(@Login Member loginMember, Model model)
    {

        if(loginMember == null)
            return "home";

        // 세션이 유지되면 로그인으로 이동동
        model.addAttribute("member",loginMember);

        return "loginHome";

    }
}

 

@Target(ElementType.PARAMETER) // @Login Annotation의 target은 매개변수(Parameber)
@Retention(RetentionPolicy.RUNTIME) // retention : 유지
public @interface Login {
    

}

@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {


    @Override
    public boolean supportsParameter(MethodParameter parameter) {

        log.info("supportsParamter() 실행 시작");

        // 1. 컨트롤러 메서드의 매개변수(Paramter)에 @Login 애노테이션이 있는 지 여부
        boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);

        // 2. @Login이 붙어 있는 매개변수가 Member 타입인지를 체크
        boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType());

        // 1과 2를 모두 만족하면 resolveArgument() 실행
        return hasLoginAnnotation && hasMemberType;

    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        log.info("resolveArgument() 실행");

        HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();

        HttpSession session = request.getSession(false);
        if(session == null){
            return null; // 해당 컨트롤러 메서드의 매개변수(Member)에 null을 매핑함!
        }

        // 해당 컨트롤러 메서드의 매개변수(Member)에 해당 세션 value를 매핑함!
        return session.getAttribute(SessionConst.LOGIN_MEMBER);

    }

}

 

@Configuration
public class WebConfig implements WebMvcConfigurer {

   
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {

        resolvers.add(new LoginMemberArgumentResolver());


    }
}

 

이와 같이 공통 작업 같은 경우 ArgumentResolver를 이용하면 매우 편리하다

-> 개발자는 @Login만 컨트롤러에서 붙여주면 그만이다. 

(물론 공통 기능은 서블릿 필터, 스프링 인터셉터를 이용해도 된다)