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 |