코딩스토리

HttpMessageConverter 본문

Spring/Spring 공부

HttpMessageConverter

kimtaehyun98 2022. 1. 16. 02:41

동아리에서 프로젝트를 진행하게 되면서 안드로이드 단에서 사용할 REST API를 개발하게 되었다.

 

Spring에서 REST API를 구축하면 보통 아래와 같이 컨트롤러를 만든다.

 

@ResponseBody
@PostMapping("/user")
public String logUserData(@RequestBody String username) {
	log.info("username = {}", username);
	return "ok";
}

안드로이드 단에 이 API 설계 문서를 넘겨주면 JSON을 사용하여 서버에 요청하고 우리는 JSON으로 반환해줄 것이다.

 

음..?

 

갑자기 궁금해진 것이 도대체 이 코드에서 어딜 봐서 JSON으로 통신한다는 것을 명시하고 있지?

어떻게 JSON으로 통신한다는 것을 알지?

 

갑자기 멍...

 

이상함을 차근차근 해결해 나가 보자.

 

먼저 @RequestBody에 대해 알아야 한다. 

 

클라이언트가 서버로 요청 데이터를 전달할 때에는 크게 3가지 방법이 있다고 한다.

 

1. GET 메서드 = 쿼리 파라미터

2. POST 메서드 = HTML Form

3. HTTP 메시지 body에 직접 담아서 요청

 

이때 REST API는 HTTP 메시지 본문에 data를 넣어 보낸다는 것이 중요하다.

즉 REST API는 3번 방법을 사용하여 서버와 클라이언트 간에 통신을 한다.

 

3번과 같은 방식으로 클라이어언트에서 전달 시에 사용하는 것이 바로 @RequestBody이다.

 

사실 이름만 봐도 RequestBody, 즉 요청 본문이란 뜻이니까 얼마나 친절한가 🤣

 

결국 @RequestBody란 요청 본문에 담겨있는 data를 읽겠다는 의미이다.

 

요청 본문에는 다음과 같이 JSON data가 있을 것이다.

 

그럼 여기서 드는 궁금증은 data를 읽어낸다면 String 전체인 " "username" : "kimtaehyun98" "이 읽혀야 하는 것 아닌가?

 

분명 무엇인가가 JSON 코드를 자동으로 변환해주고 있는 게 확실하다!

 

이러한 부분을 바로 HttpMessageConverter가 실행해준다.

 

만약 요청이나 응답이 JSON 형식으로 온다면 HttpMessageConverter가 이를 인지하고 Controller, 즉 서버에서 사용할 수 있게 가공하여 반환해준다.

그렇기 때문에 우리가 따로 JSON 데이터를 객체로 변환하거나 파싱 해서 사용할 필요가 없는 것이다.

 

요청 과정을 글로 표현하면 다음과 같다.

 

1) HTTP 요청이 오고 컨트롤러에서 @RequestBody 파라미터를 사용한다

2) HttpMessageConverter가 메시지를 읽을 수 있는지 확인하기 위해 'canRead()'를 호출한다

    - 대상 클래스 타입을 지원하는가 ex) @RequestBody의 대상 클래스(String, 아래 예시에서는 UserData)

    - HTTP 요청의 Content-Type 미디어 타입을 지원하는가 (text/plain, application/json 등)

3) canRead() 조건을 만족하면 read()를 호출해서 객체 생성하고 반환

 

 

 

다음은 실제 POSTMAN을 사용하여 테스트하는 과정이다.

 

Controller 코드

@ResponseBody
	@PostMapping("/user")
	public UserData logUserData(@RequestBody UserData data) {
		log.info("username={}, age={}", data.getUsername(), data.getAge());
		return data;
	}

 

POSTMAN 실행 화면

요청의 Content-Type

 

서버 단에 들어온 데이터 log

 

분명 JSON으로 보냈지만 Controller에서는 바로 객체로 사용 가능하였고, 이를 다시 객체로 반환했지만 응답은 JSON으로 나갔다.

 

이러한 과정을 HttpMessageConverter가 뒤에서 열심히 해주고 있는 것이다.

 

HttpMessageConverter 역시 Interface로 구현되어 있기 때문에 여러 구현체들이 존재한다.

 

대표적으로는 다음과 같다.

...
ByteArrayHttpMessageConverter
StringHttpMessageConverter 
MappingJackson2HttpMessageConverter
...

 

즉 어떠한 요청이 온다면 위의 여러 구현체들을 돌며 canRead()한 지 확인 후 가능하다면 해당 컨버터를 실행하여 우리가 서버단에서 데이터를 쉽게 사용할 수 있게 바꿔주는 것이다.

 

 

해당 부분을 공부하며 다시 한번 Spring의 위대함을 느꼈다 😂

Comments