본문 바로가기

TIL

[TIL 2022-1-30] 스프링 MVC 공부, 비트연산자

비트 연산자 종류 

 

| : 둘중 하나만 1이면 1

& : 둘다 1이여야지만 1

^ : 둘이 다르면 1

 

~ : 1 이면 0, 0 이면 1로 반전

<< n : 지정한 수 n만큼 왼쪽으로 비트 이동

>> n : 지정한 수 n만큼 오른쪽으로 비트 이동

 

 

Spring MVC Http 요청 메시지 바디 처리

요청 파라미터의 경우는 @RequestParam, @ModelAttribute 을 통해 조회했다. 또  컨트롤러 메소드 파라미터의 변수명(또는 객체 멤버의 변수명)과 요청파라미터의 키가 같다면 이를 생략하더라도 동작했다.

 

파라미터가 아닌 Http 요청 메세지 바디를 통해 데이터를 전달할 경우 @RequestBody 를 통해 데이터를 바인딩할 수 있다. 단 @RequestBody는 생략할 수 없다. 생략하면 스프링에서 단순타입(string, int) 등에 파라미터는 @RequestParam, 이외의 객체들은 @ModelAtrribute 가 적용되기 떄문에 Http 메시지 바디를 통해 데이터를 받을 경우 꼭 @RequestBody를 명시 해주어야 한다.

 

Spring MVC Http 응답 메시지 바디 처리

동적으로 HTTP 응답 코드를 변경하려면 ResponseEntry 객체를 사용한다. 그게 아니라면 컨트롤러 메소드에 @ResponseStatus(HttpStatus.OK) 와 같이 정적으로 설정 가능하다.

 

 

HandlerMethodArgumentResolver

스프링 MVC 의 @Controller 를 통해 컨트롤러 메소드를 구현할 때 30 개가 넘는 파라미터들을 자유롭게 사용할 수 있다아래는 그 파라미터들의 목록이다.

 

Method Controller 에 가능한 매개변수 목록

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments

 

Web on Servlet Stack

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,” comes from the name of its source module (spring-webmvc), but it is more com

docs.spring.io

이렇게 다양한 매개변수를 사용할 수 있는건 RequestMappingHandlerAdapter가 HandlerMethodArgumentResolver

를 호출하기때문이다. 핸들러 어댑터는 핸들러의 파라미터를 보고, 필요한 객체들을 ArgumetnResolver를 통해 제공받는다. 제공받는 객체들을 사용해서 핸들러를 호출하는 방식으로 핸들러는 작동한다. 아래 코드는 ArgumetnResolver의 정의이다.

HandlerMethodArgumentResolver 정의

supportsParameter를 통해 해당 파라미터가 지원하는 파라미터인지 조회하고, 맞다면 resolveArgument 메소드를 통해 해당 객체를 만들어 반환해준다. 

 

이를 구현한 아규먼트 리졸버들은 위 Spring 매개변수 목록에 존재하는 만큼의 리졸버 구현체들이 존재하고, 핸들러어댑터는 이 리졸버들을 하나씩 호출하면서 핸들러가 받는 매개변수가 맞는지 조회하고 맞으면 해당하는 객체를 반환받아 핸들러를 호출할 때 넣어준다.

 

이와 비슷하게 HandlerMethodReturnValueHandler 는 컨트롤러 메소드의 반환값이 ModelAndView, @Responsebody, HttpEntity, String 일 때 이에맞게 처리해주는 역할을 한다.

 

정리하면 핸들러어댑터는 컨트롤러 메소드의 매개변수를 확인하고 호출하기위해 ArgumentResolver를, 반환값에따라 뷰템플릿을 조회할지, HTTP 메소드 바디에 바로 넣을지 등을 결정하는 ReturnValueHandler를 사용한다.

 

 

HTTP 메시지 컨버터

HTTP 요청 파라미터가 아닌 메시지 바디를 통해 데이터를 받을 때,  @RequestBody 나 HttpEntry<>를 사용해 텍스트 또는 Json 을 변수 또는 객체에 매핑하여 얻을 수 있었다. 또, @ResponseBody를 사용하거나 HttpEntry 객체 반환을 통해 뷰템플릿을 조회하는 과정을 거치지 않으면서 HTTP 응답 메시지에 데이터를 문자열 또는 json 형식으로 넣을 수 도 있었다.

 

HttpMessageConverter는 이처럼 HTTP 메시지 바디를 직접 읽거나 쓸 때 편리하게 해주기 위한 인터페이스이다.

Spring MVC는 아래 두가지 방법을 사용할 때 HttpMessageConverter을 적용한다.

  1. HTTP 요청시 @RequestBody, HttpEntity(RequestEntry)
  2. HTTP 응답시 @ResponseBody, HttpEntity(ResponseEntry)

HttpMessageConverter에서는 canRead()와 read() 메소드를 통해 요청 메시지 바디를 읽고, canWrite()와 write() 메소드를 통해 응답 메시지 바디를 작성하여 요청과 응답 메시지에 모두 관여하는 양방향 인터페이스이다.

 

이를 상속받아 기본적인 문자처리는 StringHttpMessageConveter, 객체처리는 MappingJackson2HttpMessageConverter 가 담당한다. (바이트 처리는 ByteArrayHttpMessageConverter) 이외에도 스프링MVC는 매우 많은 HTTP 메시지 컨버터를 제공한다.

 

StringHttpMessageConveter는 클래스타입이 String일 때, MappingJackson2HttpMessageConverter는 미디어타입이 'application/json'이고 클래스 타입이 객체 또는 HashMap일 때만 적용된다.

 

 

HTTP 메시지 컨버터 호출 시점

위에서 말한 것처럼 @RequestMapping을 통한 컨트롤러 메소드들의 매개변수와 반환값을 처리하는 ArgumentResolver들과 ReturnValueHandler들이 있다. 

 

때문에 @ResponseBody, HttpEntity, @RequestBody 에 대한 아규먼트 리졸버들과 리턴 밸류 핸들러 또한 존재한다. 여기서 컨버터가 호출된다.