Spring

[SpringBoot] ArgumentResolver 사용하여 jwt 정보 가져오기

codi-3 2024. 9. 4. 16:18

스프링 부트에서 API controller를 생성할 때 가끔 정보를 가져오기 위해 httpservletrequest에서 정보를 받아와 사용하였다. 하지만 Service에 httpservletreqeust를 바로 전달하는 것은 3 Layer Architecture에 위반한다고 들어 Argument Resolver를 사용하는 방법을 이번 프로젝트에 응용해 보았다.


 🚀 ArgumentResolver

 

ArgumentResolver는 Spring MVC에서 컨트롤러 메서드의 매개변수를 해석하고 주입하는 기능을 확장하기 위해 사용된다. 일반적으로, Spring MVC는 기본적인 매개변수 유형에 대해 자동으로 매핑을 해주지만, 복잡한 객체나 특수한 상황에서는 이 기능을 확장해야 할 때가 있다. 이때 ArgumentResolver를 사용한다.

주요 역할:

컨트롤러 메서드의 매개변수에 대해 특정한 로직을 적용하여 값을 주입하는 기능을 제공한다. 예를 들어, 사용자 정의 객체를 매개변수로 받을 때, 해당 객체를 생성하거나 특정한 방식으로 초기화하고 싶을 때 사용할 수 있다.

구현 방법:

  1.  HandlerMethodArgumentResolver 인터페이스 구현
    • supportsParameter(MethodParameter parameter): 이 메서드는 현재 매개변수가 ArgumentResolver에서 지원하는 타입인지 여부를 반환합니다. 이 메서드가 true를 반환하면, 해당 매개변수에 대해 resolveArgument 메서드가 호출된다.
    • resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory): 이 메서드는 실제로 매개변수를 해석하고, 주입할 값을 반환한다.
  2.  사용 시나리오:
  • 사용자 정의 객체를 컨트롤러 메서드에서 직접 받으려는 경우
  • 요청에 따라 특정 객체를 동적으로 생성하고 싶은 경우
  • 특정한 전처리나 후처리가 필요한 경우

이를 통해 코드의 재사용성과 유연성을 높일 수 있으며, Spring MVC가 제공하는 기본적인 매개변수 주입 기능을 확장할 수 있다.


🔡 예시

 

public class AuthUserArgumentResolver implements HandlerMethodArgumentResolver {

    // @Auth 어노테이션이 있는지 확인
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        boolean hasAuthAnnotation = parameter.getParameterAnnotation(Auth.class) != null;
        boolean isAuthUserType = parameter.getParameterType().equals(AuthUser.class);
        if(hasAuthAnnotation != isAuthUserType) {
            throw new IllegalArgumentException("@Auth Annotation 와 AuthUser Type 은 함꺠 사용되어야 합니다.");
        }
        return hasAuthAnnotation;
    }

    // AuthUser 객체를 생성하여 반환
    @Override
    public Object resolveArgument(
            @Nullable MethodParameter parameter,
            @Nullable ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            @Nullable WebDataBinderFactory binderFactory
    ) {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();

        // JwtFilter 에서 set 한 userId, email 값을 가져옴
        Long userId = (Long) request.getAttribute("userId");
        String userName = (String) request.getAttribute("userName");
        String email = (String) request.getAttribute("email");

        return new AuthUser(userId, userName, email);
    }
}

 

위코드를 사용하면 먼저 컨트롤러에 @Auth annotation과 클래스 타입이 AuthUser 인지 확인해 준다. 그 뒤 JWT 토큰에서 request에 담아주었던 값들 (이경우에는 userId, userName, email)등을 받아와 알맞은 데이터 타입으로 저장한 뒤 AuthUser 생성자에 대입하여 객체를 생성한 뒤 반환해 준다.

 

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

@Getter
public class AuthUser {
    private final Long id;
    private final String userName;
    private final String email;

    public AuthUser(Long id,String userName,String email){
        this. id = id;
        this.userName = userName;
        this.email = email;
    }
}

Auth annotation과 AuthUser 파일 내 코드는 위와 같다. @Target,@Retention을 사용한 뒤 @Inteface로 Auth annotation을 커스텀으로 생성하여 사용할 수 있다. AuthUser클래스내부에는 원하는 필드명과 타입을 지정해 준 뒤 생성자를 만들어주면 된다.

 

Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

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

그 뒤 Webconfig 클래스를 사용하여 Argument resolver를 등록하여 사용하면 된다. WebConfig는 WebMvcConfiguerer 인터페이스를 implement 받아 Spring MVC configuration을 커스텀할 수 있게 한다. 

 

이를 사용하여 위에 등록한 AuthUserArgumentResolver를 Spring MVC에 등록하여 @Auth 어노테이션 밑 AuthUser를 사용하여 원하는 데이터를  위와 같이받아올 수 있게 해 준다.

'Spring' 카테고리의 다른 글

[SpringBoot]MyBatis  (2) 2024.10.01
[SpringBoot]Api Response  (0) 2024.09.06
[SpringBoot]Entity 연관관계 방향성  (0) 2024.08.29
[SpringBoot] NaverOpen API 사용  (0) 2024.08.29
[SpringBoot]환경변수 application.properties  (0) 2024.08.28