728x90
반응형
SMALL

참고자료

 

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 강의 | 김영한 - 인프런

김영한 | 웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습

www.inflearn.com

 

ArgumentResolver 활용

ArgumentResolver를 사용해서, 세션에 있는 로그인 한 유저를 굉장히 간단하게 가져오는 방법을 소개한다.

 

다음 코드를 보자.

@GetMapping("/")
public String home(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member member,
                             Model model) {
    if (member == null) {
        return "home";
    }

    model.addAttribute("member", member);
    return "loginHome";
}
  • 웹 애플리케이션의 홈 경로이다. 세션에 저장된 로그인 한 유저를 찾기 위해 @SessionAttribute를 사용해서 가져오는 모습이다. 이것이 나쁘다는 게 아니라 이 코드가 아래처럼 바뀔 수 있다.
@GetMapping("/")
public String homeWithArgumentResolver(@Login Member loginMember, Model model) {
    if (loginMember == null) {
        return "home";
    }

    model.addAttribute("member", loginMember);
    return "loginHome";
}
  • @Login 이라는 애노테이션을 개발자가 직접 만들고 이 애노테이션이 달린 파라미터에 로그인 한 유저를 자동으로 넣어주는 것이다.

 

ArgumentResolver는 말 그대로 파라미터의 애노테이션을 사용해서 어떤 처리를 해주겠다는 의미이다. 저렇게 사용하면 로그인 한 유저를 가져오려고 할때마다 꽤나 편리하게 사용할 수 있을 것 같다. 

 

ArgumentResolver를 위한 애노테이션 생성

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를 위한 HandlerMethodArgumentResolver 구현

LoginMemberArgumentResolver

package hello.login.web.argumentresolver;

import hello.login.domain.member.Member;
import hello.login.web.session.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;
import java.util.Optional;

@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        log.info("[supportsParameter] 실행");

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

        return hasLoginAnnotation && hasMemberType;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) throws Exception {
        log.info("[resolveArgument] 실행");

        HttpServletRequest req = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        if (req == null) {
            return null;
        }

        HttpSession session = req.getSession(false);
        if (session == null) {
            return null;
        }

        return session.getAttribute(SessionConst.LOGIN_MEMBER);
    }
}
  • 애노테이션을 만들었으면 이 애노테이션이 어떤 것을 할지 정의해줘야 한다. 그러기 위해 HandlerMethodArgumentResolver를 구현한다.
  • supportsParameter(MethodParameter methodParameter): 이 메서드에서 `true`를 반환해야만 resolveArgument가 실행된다. 이 메서드에서 우선 1.애노테이션이 @Login인지 확인한다. 2. 애노테이션이 달린 파라미터의 타입이 Member인지 확인한다. 이 두개를 모두 만족하면 resolveArgument 메서드를 실행한다.
  • resolveArgument(): 여기서는 해당 파라미터에 어떤 값을 넣어줄 지 결정한다. 우리가 원하는 건 세션에 있는 로그인 한 사용자를 파라미터에 넣으려고 한다. 그래서 파라미터로 제공되는 NativeWebRequestHttpServletRequest로 캐스팅하여 세션을 가져와서 세션에 로그인 한 유저를 저장할 때 사용했던 키를 통해 로그인 한 유저를 반환한다. 없다면 null을 반환하면 된다.

ArgumentResolver를 위한 WebMvcConfigurer 설정

package hello.login;

import hello.login.web.argumentresolver.LoginMemberArgumentResolver;
import hello.login.web.interceptor.LoggingInterceptor;
import hello.login.web.interceptor.LoginCheckInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginMemberArgumentResolver());
    }
}
  • WebMvcConfigurer가 가지고 있는 메서드 중 addArgumentResolvers를 구현한다. 여기서 만든 LoginMemberArgumentResolver를 추가하면 된다.

 

ArgumentResolver 테스트

@GetMapping("/")
public String homeWithArgumentResolver(@Login Member loginMember, Model model) {
    if (loginMember == null) {
        return "home";
    }

    model.addAttribute("member", loginMember);
    return "loginHome";
}
  • 이제 로그인이 된 경우 이 홈 경로로 들어오면 loginMember에 로그인 한 유저가 들어온다.

 

스프링 MVC에서는 이렇게 간단하지만 편리한 기능을 만들 수 있다.

728x90
반응형
LIST

+ Recent posts