Spring

@ResponseBody , @RequestBody

goodbye 2021. 10. 23. 11:47

@RequestBody 를 통해서 자바 객체로 Conversion 을 할때 그냥 변환되는것이 아니라 HttpMessageConverter 를 사용하는데 아래의 메서드에 각종의 메시지 컨버터가 설정되어 있다.

 

WebMvcConfigurationSupport.addDefaultHttpMessageConverters

 

만약 요청이 JSON으로 들어온 경우 요청 해더(request header)에 컨텐츠 타입(Content-Type)을 알려줘야 한다. 그러면 헤더에 있는 컨텐츠 타입을 보고 JSON을 컨버팅 할 수 있는 컨버터(Jackson2ObjectMapperBuilder)를 사용하겠다고 JSON을 자바 객체로 변환하는 메시지 컨버터를 사용하여 본문에 담긴 데이터를 자바 객체로 변환하게 된다.

 

/* @RequestBody를 통해 자바 객체로 변환할때 HttpMessageConverter를 사용하여
* 헤더에 담긴 컨텐츠 타입을 보고 어떤 메시지 컨버터를 사용할 것인지 판단하여
* 요청 본문에 담긴 값을 자바 객체로 변환한다 
*/
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
  Hello hello = new Hello();
  hello.setName(name);
  return hello;
}

Jackson2ObectMapperBuilder는 스프링부트에서 JacksonAutoConfiguration클래스에서 자동으로 설정하기 때문에 별다른 설정없이 JSON을 자바객체로 변환하는 ObjectMapper를 사용 할 수 있다.

 

Jackson2ObjectMapperBuilder 내부를 보면  autoDetectGetterSetter() 라는 메서드를 사용하는데 이는 JSON 타입으로 변환하기 위한 객체(DTO)에 getter와 setter 메서드가 존재해야 한다는 것을 의미한다

 

public Jackson2ObjectMapperBuilder autoDetectGettersSetters(boolean autoDetectGettersSetters) {
    this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters);
    this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters);
    this.features.put(MapperFeature.AUTO_DETECT_IS_GETTERS, autoDetectGettersSetters);
    return this;
}

만약 getter/setter가 존재하지 않으면 응답 메세지를 보낼때 Jackson2ObjectMapperBuilder를 제대로 사용하지 못해서 JSON 타입으로 변환이 처리되지 않기때문에 클라이언트에서 success()함수로 결과값을 받아 올 수 없다

 

static class Hello{
  private String name;
  
  // getter, setter ==> java bean 표준방식
  // property 접근방식이라고도 한다
  
  public String getName() {
  	return name;
  }

  public void setName(String name) {
  	this.name = name;
  }
}

스프링 부트의 pom.xml을 보면 spring-boot-starter-web이 존재하는데 내부에 들어가보면  jackson-databind 의존성이 자동으로 잡혀있는것을 볼수 있다. 해당 의존성이 있어야 JSON 타입으로 제대로 변환이 된다.

 

@RequestBody 역할

이 어노테이션이 붙은 파라미터에는 http요청의 본문(body)가 그대로 전달된다.

HTTP요청의 바디내용을 통째로 자바객체로 변환해서 매핑된 메서드 파라미터로 전달해준다

 

@ResponseBoby 역할

자바객체를 HTTP요청의 바디 내용으로 매핑하여 클라이언트로 전송한다

@ResponseBOdy가 붙은 파라미터가 있으면 HTTP요청의 미디어타입과 파라미터의 타입을 먼저 확인한다

- dispatcher-servlet.xml의 <annotiation-drvien>태그 내에 선언하는 <message-converter>에서 확인

- 메세지 변환기중에서 해당 미디어 타입과 파라미터 타입을 처리할수 있다면  HTTP 요청의 본문 부분을 통째로 변환해서 지정된 메서드 파라미터로 전달해준다

즉 @ResposeBody 을 사용하면 http 요청  body를 자바 객체로 전달받을수 있다

 

<mvc:annotation-driven>
	<mvc:message-converters>
    	<bean class="org.springframework.http.converter.StringHttpMessageConverter">
        	<property name="supportedMediaTypes">
            	<list>
                	<value>text/html;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

 

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB접근 기술

@ResponseBody를 사용하면

 - HTTP Body에 문자 내용을 직접 반환한다

 - viewResolver 대신에 HttpMessageConverter가 동작한다

 - 기본 문자처리는 StringHttpMessageConverter가 담당

 - 기본 객체처리는 MappingJackson2HttpMessageConverter가 담당

 - byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있다

 

 

MessageConverter의 종류

- StringHttpMessageConverter

- FormHttpMessageConverter

- ByteArrayMessageConverter

- MarshallingHttpMessageConverter

- SourceHttpMessageConverter

- BufferedImagedHttpMessageConverter

- MappingJacksonHttpMessageConverter

   - Jackson's ObjectMappter 를 사용하여 request, response 를 JSON 으로 변환할때 사용되는 MessageConverter

   - applicaton/json 을 지원한다.

 

 

@RestController

@Controller와는 다르게 RestController는 리턴값이 자동으로 @ResponseBody가 붙게되어 별도 어노테이션을 명시해주지 않아도 HTTP 응답데이터 body에 자바 객체가 매핑되어 전달된다

- @Controller인 경우에 body를 자바객체로 받기 위해서는 @ResponseBody 어노테이션을 반드시 붙여야한다

 

정리하면

클라이언트에서 서버로 필요한 데이터를 전송하기 위해서 JSON이라는 데이터를 요청 본문에 담아서 서버로 보내면, 서버에서는 @RequestBody 어노테이션을 사용하여 http 요청 본문에 담긴 값들을 자바 객체로 변환시켜 객체에 저장한다.

 

서버에서 클라이언트로 응답 데이터를 전송하기 위해서 @ResponseBody를 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하여 클라이언트로 전송한다