코드 그라데이션

HTTP 요청 메시지 - JSON 본문

Spring/MVC 1

HTTP 요청 메시지 - JSON

완벽한 장면 2023. 10. 10. 11:45

HTTP 요청 메시지 - JSON

이번에는 HTTP API에서 주로 사용하는 JSON 데이터 형식을 조회하기

 

V1 - 기존 서블릿에서 사용했던 방식

RequestBodyJsonController

@Slf4j
@Controller
public class RequestBodyJsonController {
	// ObjectMapper 객체를 생성. 
    // ObjectMapper는 JSON 데이터를 자바 객체로 변환하거나 자바 객체를 JSON으로 직렬화하는 데 사용.
	private ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("/request-body-json-v1")
	public void requestBodyJsonV1(HttpServletRequest request,
                              HttpServletResponse response) throws IOException {
    	// HTTP 요청의 입력 스트림을 얻어온다. 
        // 이 입력 스트림은 요청 바디에 있는 데이터를 읽기 위해 사용.
    	ServletInputStream inputStream = request.getInputStream();
    
    	// 입력 스트림에서 데이터를 읽어와 문자열로 변환.
   		String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
    
    	// 로그에 읽어온 메시지 바디를 출력.
    	log.info("messageBody={}", messageBody);
    
   		// ObjectMapper를 사용하여 JSON 문자열을 HelloData 클래스의 객체로 변환.
    	HelloData data = objectMapper.readValue(messageBody, HelloData.class);
    
    	// 변환된 객체에서 사용자 이름(username)과 나이(age)를 가져와 로그에 출력.
    	log.info("username={}, age={}", data.getUsername(), data.getAge());
    
    	// HTTP 응답에 "ok" 문자열을 쓰고 응답을 완료함.
    	response.getWriter().write("ok");
	}
}

 

Postman 테스트

POST http://localhost:8080/request-body-json-v1
raw, JSON, content-type: application/json
{"username":"hello", "age":20}

 

실행하면

 

잘 출력 됨을 확인할 수 있음

 


requestBodyJsonV2 - @RequestBody 문자 변환

/**
* @RequestBody
* HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
*
* @ResponseBody
* - 모든 메서드에 @ResponseBody 적용
* - 메시지 바디 정보 직접 반환(view 조회X)
* - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
* @ResponseBody 어노테이션을 사용하여 이 메서드가 메시지 바디 정보를 직접 반환하고 
* 뷰를 조회하지 않도록 설정. 이것은 일반적으로 RESTful API 엔드포인트에서 사용됨.
*/


@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {
    // JSON 형식의 메시지 바디를 문자열로 전달받아서, 
    // ObjectMapper를 사용하여 HelloData 객체로 변환.
    HelloData data = objectMapper.readValue(messageBody, HelloData.class);
    
    // 변환된 객체에서 사용자 이름과 나이를 가져와 로그에 출력.
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    
    // "ok" 문자열을 반환. 이 문자열은 HTTP 응답의 바디에 들어간다.
    return "ok";
}

 

 

고민

문자로 변환하고 다시 json으로 변환하는 과정이 불편하다. @ModelAttribute처럼 한번에 객체로
변환할 수는 없을까?

 


 

requestBodyJsonV3 - @RequestBody 객체 변환

    /**
     * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
     * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (contenttype: application/json)
     */

    @ResponseBody
    @PostMapping("/request-body-json-v3")
    public String requestBodyJsonV3(@RequestBody HelloData data) {
        // @RequestBody 어노테이션을 사용하여 JSON 데이터를 자동으로 HelloData 객체로 변환하고,
        // 이 객체를 메서드 매개변수로 직접 전달받는다.

        // 변환된 객체에서 사용자 이름과 나이를 가져와 로그에 출력.
        log.info("username={}, age={}", data.getUsername(), data.getAge());

        // "ok" 문자열을 반환합니다. 이 문자열은 HTTP 응답의 바디에 들어간다.
        return "ok";
    }

 

 

@RequestBody 객체 파라미터

  • @RequestBody HelloData data
  • @RequestBody에 직접 만든 객체를 지정할 수 있다.


- HttpEntity, @RequestBody 를 사용하면 HTTP 메시지 컨버터가

  HTTP 메시지 바디의 내용을 우리가 원하는 문자나 객체 등으로 변환해준다.
- HTTP 메시지 컨버터는 문자 뿐만 아니라 JSON도 객체로 변환해주는데,

  우리가 방금 V2에서 했던 작업을 대신 처리해준다.
- 자세한 내용은 뒤에 HTTP 메시지 컨버터에서 다룬다.

 

@RequestBody는 생략 불가능

 @ModelAttribute 에서 학습한 내용을 떠올려보자.

 

스프링은 @ModelAttribute , @RequestParam 과 같은 해당 애노테이션을 생략시 다음과 같은 규칙을 적용한다.
* String , int , Integer 같은 단순 타입 = @RequestParam
* 나머지 = @ModelAttribute (argument resolver 로 지정해둔 타입 외)

 

따라서 이 경우 HelloData에 @RequestBody 를 생략하면 @ModelAttribute 가 적용되어버린다.
HelloData data =>  @ModelAttribute HelloData data
따라서 생략하면 HTTP 메시지 바디가 아니라 요청 파라미터를 처리하게 된다.

 

 

물론 앞서 배운 것과 같이 HttpEntity를 사용해도 된다.

 


 

requestBodyJsonV4 - HttpEntity

@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
    // HttpEntity를 사용하여 요청 바디를 다룬다. 
    // HttpEntity는 HTTP 요청과 응답의 헤더와 바디를 쉽게 다루기 위한 클래스.
    
    HelloData data = httpEntity.getBody();
    
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    
    return "ok";
}

 

- HttpEntity는 HTTP 요청과 응답의 헤더 및 바디를 포함하는 객체이다.

- httpEntity.getBody()를 사용하여 요청 바디에서 JSON 데이터를 HelloData 객체로 가져온다.

  이 객체에는 요청 바디의 내용이 자동으로 매핑된.

 


 

requestBodyJsonV5

/**
 * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
 * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (contenttype: application/json)
 *
 * @ResponseBody 적용
 * - 메시지 바디 정보 직접 반환(view 조회X)
 * - HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter 적용 (Accept: application/json)
 */

@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
    // @RequestBody 어노테이션을 사용하여 JSON 데이터를 자동으로 HelloData 객체로 변환하고,
    // 이 객체를 메서드의 반환값으로 직접 반환합니다. 이 메서드는 HelloData 객체를 JSON으로 직렬화하여 
    //클라이언트에게 응답으로 전송.
    
    // 변환된 객체에서 사용자 이름과 나이를 가져와 로그에 출력
    log.info("username={}, age={}", data.getUsername(), data.getAge());
    
    // HelloData 객체를 반환. 이 객체는 JSON으로 변환되어 HTTP 응답의 바디에 들어간다.
    return data;
}

 

728x90
Comments