Java Category/Spring

[Spring MVC] ArgumentResolver 를 이용한 @Login 어노테이션 구현

ReBugs 2024. 3. 20.

이 글은 인프런 김영한님의 Spring 강의를 바탕으로 개인적인 정리를 위해 작성한 글입니다.


@Login 애노테이션이 있으면 직접 만든 ArgumentResolver 가 동작해서 자동으로 세션에 있는 로그인 회원을 찾아주고, 만약 세션에 없다면 null 을 반환하도록 개발

 

HomeController - 추가

기존

@GetMapping("/")
public String homeLoginV3Spring(
        @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false)
        Member loginMember,
        Model model) {

        //세션에 회원 데이터가 없으면 home
        if (loginMember == null) {
        return "home";
    }

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

 

변경

@GetMapping("/")
public String homeLoginV3ArgumentResolver(@Login Member loginMember, Model model) {
    //세션에 회원 데이터가 없으면 home
    if (loginMember == null) {
        return "home";
    }

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

 

 

@Login 애노테이션 생성

@Target(ElementType.PARAMETER) //타겟은 파라미터 레벨
@Retention(RetentionPolicy.RUNTIME) //런타임까지 어노테이션 정보가 남아있음
public @interface Login {
}

 

LoginMemberArgumentResolver 생성

HandlerMethodArgumentResolver 인터페이스의 boolean supportsParameter(), Object resolveArgument() 를 오버라이딩해야 한다.

@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        log.info("supportsParameter 실행");
        boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class); //현재 처리 중인 메서드 파라미터에 @Login 어노테이션이 적용되어 있는지 여부를 확인
        boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType()); //파라미터의 타입이 Member 클래스 또는 그 하위 클래스의 인스턴스인지 확인
        return hasLoginAnnotation && hasMemberType; //둘 다 만족한다면 true 리턴, true -> resolveArgument() 메서드 호출
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        log.info("resolveArgument 실행");
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); //HttpServletRequest로 캐스팅하여 실제 서블릿 요청에 접근
        HttpSession session = request.getSession(false); //세션이 존재하지 않을 경우 새로 생성하지 않도록 지정
        if (session == null) {
            return null;
        }
        return session.getAttribute(SessionConst.LOGIN_MEMBER); //세션의 loginId 키를 이용하여 member 객체를 가져와서 리턴
    }
}

supportsParameter(MethodParameter parameter)

이 메서드는 현재 처리 중인 메서드 파라미터가 이 리졸버에 의해 지원되는지 여부를 결정한다. 여기서는 두 가지 조건을 검사한다

  • hasLoginAnnotation: 메서드 파라미터에 @Login 어노테이션이 적용되었는지 여부를 확인한다.
  • hasMemberType: 파라미터 타입이 Member 클래스 또는 그 하위 클래스의 인스턴스인지 확인한다.
    두 조건이 모두 만족할 때만 true를 반환하여 이 파라미터를 처리할 수 있음을 나타낸다.(true -> resolveArgument() 메서드 호출)

 

resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)

이 메서드는 실제로 파라미터 값의 해석을 담당한다. 여기서는 HTTP 요청과 관련된 HttpServletRequest에 접근하여 세션에서 Member 객체를 추출한다.

  • request.getSession(false): 이 호출은 현재 요청과 관련된 세션이 이미 존재하지 않을 경우 null을 반환하도록 지정한다. 즉, 새 세션을 생성하지 않는다.

세션에서 SessionConst.LOGIN_MEMBER 속성을 사용하여 로그인한 회원 객체를 가져온다. 이 객체는 컨트롤러 메서드에서 @Login 어노테이션이 적용된 Member 타입 파라미터에 주입된다.

 

WebMvcConfigurer에 설정 추가

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginMemberArgumentResolver()); //LoginMemberArgumentResolver 등록
    }
    ...
}

WebMvcConfigurer 인터페이스는 스프링 MVC의 웹 구성을 커스터마이징할 수 있게 해주는 중요한 인터페이스이다. 스프링 부트 사용 시 자동 구성이 많은 부분을 처리해주지만, 애플리케이션의 특정 요구 사항에 맞추어 MVC 구성을 세밀하게 조정하고 싶을 때 WebMvcConfigurer 인터페이스를 구현하는 클래스를 생성하여 사용한다.



주요 사용 사례

  • 인터셉터 추가: HTTP 요청을 가로채어 전처리 및 후처리 로직을 실행할 수 있는 인터셉터를 등록한다.
  • 리소스 핸들러 추가: 정적 리소스에 대한 요청을 처리하기 위한 리소스 핸들러를 등록한다.
  • 메시지 컨버터 추가 또는 변경: HTTP 요청 본문을 객체로 변환하거나 객체를 HTTP 응답 본문으로 변환할 때 사용되는 메시지 컨버터를 추가하거나 변경한다.
  • CORS(Cross-Origin Resource Sharing) 설정: 다른 도메인에서의 API 요청을 허용하기 위한 CORS 설정을 추가한다.
  • 뷰 컨트롤러 추가: 특정 URL 요청을 처리하기 위한 뷰 컨트롤러를 추가한다.
  • 포맷터 및 Validator 추가: 필드 포맷팅 및 검증 로직을 추가한다.
  • 전역 CORS 설정: 애플리케이션 전체에 적용되는 CORS 정책을 설정한다.

 

WebMvcConfigurer 인터페이스의 addArgumentResolvers 메서드는 스프링 MVC에서 컨트롤러 메서드의 파라미터를 처리하기 위한 커스텀 HandlerMethodArgumentResolver 인스턴스를 추가하는 기능을 제공한다. 

 

HandlerMethodArgumentResolver는 컨트롤러 메서드의 파라미터를 해석하는 역할을 담당하며, 이를 사용하여 개발자는 요청에 따라 파라미터 값을 동적으로 생성하거나 변형하여 제공할 수 있다.

 

이 메서드를 구현함으로써, 애플리케이션은 표준 파라미터 해석 방식을 넘어서는 복잡한 요구사항을 충족시킬 수 있는 유연성을 갖게 된다.

 

이렇게 ArgumentResolver 를 활 용하면 공통 작업이 필요할 때 컨트롤러를 더욱 편리하게 사용할 수 있다.

댓글