본문 바로가기
스프링/스프링 웹 개발 활용

[Spring] 로그인 처리 시 ArgumentResolver 활용하기

by drCode 2023. 11. 21.
728x90
반응형

 

 

ArgumentResolver는 요청매핑 핸들러 어댑터를 통해서 유연하게 파라미터들을 처리할 수 있게 한다.

 

ArgumentResolver는 아래의 포스팅에 설명이 되어있다.

https://drcode-devblog.tistory.com/498

 

[Spring] 요청 매핑 핸들러 어뎁터 구조

그렇다면 HTTP 메시지 컨버터는 스프링 MVC 어디쯤에서 사용되는 것일까? SpringMVC 구조 핵심은 애노테이션 기반의 컨트롤러, 그러니까 @RequestMapping 을 처리하는 핸들러 어댑터인 RequestMappingHandlerAdap

drcode-devblog.tistory.com

 

ArgumentResolver 를 이용해서 로그인 회원을 좀 더 편리하게 찾아볼 수 있다.

 

HomeController - 추가

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

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

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

 

 - homeLoginV3Spring()@GetMapping 주석 처리

 - 다음에 설명하는 @Login 애노테이션을 만들어야 컴파일 오류가 사라진다.

 

@Login 애노테이션이 있으면 직접 만든 ArgumentResolver 가 동작해서 자동으로 세션에 있는 로그인 회원을 찾아주고,

만약 세션에 없다면 null 을 반환하도록 개발해야한다.

 

@Login 애노테이션 생성

package hello.login.web.argumentresolver;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}

 - @Target(ElementType.PARAMETER) : 파라미터에만 사용

 - @Retention(RetentionPolicy.RUNTIME) : 리플렉션 등을 활용할 수 있도록 런타임까지 애노테이션 정보가 남아있음

 

 

ArgumentResolver 는 HandleMethodArgumentResolver를 이용해서 구현할 수 있다.

LoginMemberArgumentResolver 생성

package hello.login.web.argumentresolver;

import hello.login.domain.member.Member;
import hello.login.web.SessionConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {

        log.info("supportsParameter 실행");

        boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
        boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType());

        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;
        }

        return session.getAttribute(SessionConst.LOGIN_MEMBER);
    }
}

 - supportsParameter() : @Login 애노테이션이 있으면서 Member 타입이면 해당 ArgumentResolver 가 사용된다.

 - resolveArgument() : 컨트롤러 호출 직전에 호출 되어서 필요한 파라미터 정보를 생성해준다.

   여기서는 세션에 있는 로그인 회원 정보인 member 객체를 찾아서 반환해준다.

   이후 스프링MVC는 컨트롤러의 메서드를 호출하면서 여기에서 반환된 member 객체를 파라미터에 전달해준다

 

WebMvcConfigurer에 설정 추가

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

앞서 개발한 LoginMemberArgumentResolver 를 등록하자.

 

실행해보면, 결과는 동일하지만, 더 편리하게 로그인 회원 정보를 조회할 수 있다. 

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

 

 

728x90
반응형

댓글