qna-atdd 프로젝트 코드 이해하기
HandlerMethodArgumentResolver
resolve
1.해결하다 2.결의하다 3.대책을 마련하다
우선 resolve의 뜻을 찾아봤는데요. 뭔가를 해결해주는 느낌, 어떤 것들을 처리해주는 느낌이 있네요. Spring Document를 살펴보면 다음과 같은 정의를 찾을 수 있었습니다.
Strategy interface for resolving method parameters into argument values in the context of a given request.
'주어진 요청 맥락에 따라 메서드 파라미터를 값으로 하여 어떤 것을 해결해주기 위한 전략적인 인터페이스'라고 이해할 수 있겠네요. 하지만 크게 와닿지 않네요. 일단 계속해서 메서드를 살펴보겠습니다. 이 부분은 소스코드 내 주석을 통해서 이해해볼게요.
public interface HandlerMethodArgumentResolver {
/**
* Whether the given {@linkplain MethodParameter method parameter} is
* supported by this resolver.
* @param parameter the method parameter to check
* @return {@code true} if this resolver supports the supplied parameter;
* {@code false} otherwise
*/
boolean supportsParameter(MethodParameter parameter);
/**
* Resolves a method parameter into an argument value from a given request.
* A {@link ModelAndViewContainer} provides access to the model for the
* request. A {@link WebDataBinderFactory} provides a way to create
* a {@link WebDataBinder} instance when needed for data binding and
* type conversion purposes.
* @param parameter the method parameter to resolve. This parameter must
* have previously been passed to {@link #supportsParameter} which must
* have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value, or {@code null} if not resolvable
* @throws Exception in case of errors with the preparation of argument values
*/
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
이번 미션의 LoginUserHandlerMethodArgumentResolver
내에서 logger를 통해 어느 시점에 출력이 되는지 확인을 해봤는데요. 딱 로그인하는 시점에 제가 log로 찍어놓은 메시지가 뜨더라구요. 아마 수업시간에 Pobi가 말한 Interceptor개념이 적용된 것 같아요!
위 이미지를 보면 알 수 있듯이 Interceptor클래스의 preHandle()
메서드를 실행하고 나서 제가 log 메시지를 적어놓은 Resolver 클래스가 호출이 되네요. 코드를 확인해보면 제대로 로그인이 되었을 때 preHandle()
에서 true로 반환이 되는데요. 여기에서 true값이 반환되면 Resolver가 호출되는 것일까요?
Pobi의 말을 들으니 전혀 관련이 없더라구요. 대신
WebMvcConfig
가WebMvcConfigurer
를 상속받고 있는데요. 이것의 메서드addArgumentResolver()
를 Override하여 Bean으로 등록된 Resolver를 넣더라구요. Spring내에서 어떠한 List가 있는데 이 List에 Resolver를 등록시키고 이 순서에 따라 처리가 되는 것입니다.
/**
* Add resolvers to support custom controller method argument types.
* <p>This does not override the built-in support for resolving handler
* method arguments. To customize the built-in support for argument
* resolution, configure {@link RequestMappingHandlerAdapter} directly.
* @param resolvers initially an empty list
*/
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
Resolver를 추가할 때 사용되는 메서드가 정의되어 있는 인터페이스입니다.
또 하나 재미있는 부분이 있는데요. supportsParameter()
메서드에 주석처리 해놓은 부분은 한번만 호출되고 이후엔 호출이 안되고, resolveArgument()
는 매번 호출이 되더라구요. 분명 supportsParameter()
도 해당 조건에 따라 계속 호출되어야 하는 것인데 캐쉬때문에 특정 path에 대해 boolean값을 한번 호출되고 난 후부터는 기억하고 있는 것 같습니다. 하지만 supportsParameter()
는 다른 유저 처리가 각각 필요하기 때문에 꼭 매번 호출되어야 하는 것입니다.
그렇기 때문에 위에서 resolveArgument()
메서드 부분만 호출이 되는 것입니다.
Resolver 만들어보기
https://stackoverflow.com/questions/30715579/custom-spring-annotation-for-request-parameters
로그인 세션 처리과정
Resolver -> Exception발생 -> Exception통합처리에서 return
같은 유저 확인
public User findById(User loginUser, long id) {
return userRepository.findById(id)
.filter(user -> user.equals(loginUser))
.orElseThrow(UnAuthorizedException::new);
세션값 확인의 경우 Resolver를 통해 이루어지고 있지만 같은 유저인지 확인의 경우 @Service
클래스 내에서 이루어지고 있습니다.
what is @Transactional
?
COMMIT 또는 ROLLBACK을 처리하는 과정입니다. 세트로 실행하고 싶은 SQL명령은 트랜잭션 내에서 실행하는 것이 좋다고 하네요. 기본적으로 트랜잭션을 사용하지 않는한 데이터베이스의 default는 자동커밋이 됩니다.
참고 : <SQL 첫걸음>, 아사이 아츠시 지음
aop로 처리할 수 있는데 왜 굳이 resolver를 사용할까요?
if문을 줄여 복잡도를 줄이기 위해서라는 답변을 들었는데요. 이 부분에 대해서는 좀 더 고민해봐야할 것 같아요.
각 요청 처리시 공통적으로 호출되는 부분
path경로가 이동할 때마다 공통적으로 찍어주는 부분이 있는데요. 이 부분은 무엇을 의미하는 것일까요?
소스코드를 찾아보니 위에 2개는 Interceptor에서, 나머지 아래 2개는 AOP를 통해서 처리하고 있네요. AOP부분은 이후에 제가 발표에서 다루겠지만 @Around
를 이용하여 메서드 실행 전, 후로 해당 로그를 출력하고 있습니다.
What's the difference between a Handler, a Resolver and an Interceptor in Spring MVC?
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-12-12) (0) | 2018.12.12 |
---|---|
Today's Dev Notes(2018-12-11) (0) | 2018.12.11 |
Today's Dev Notes(2018-12-10) (0) | 2018.12.10 |
Today's Dev Notes(2018-12-09) (0) | 2018.12.09 |
Today's Dev Notes(2018-12-08) (0) | 2018.12.08 |