개발자로 후회없는 삶 살기
[문법] 요청과 응답, HttpMessageConverter 본문
서론
※ 과거에 기록한 내용에서 중요한 부분만 발췌하여 모두가 이해하기 쉽게 다시 서술한다.
본론
- Http 요청 메세지(단순 텍스트)
서블릿에서는 메세지 바디 데이터를 읽기 위해선 InputStream으로 바디 데이터를 스트림 데이터로 저장하고 인코딩하여 문자로 변환해야 한다.
스프링에서는 Http 바디에 있는 것을 원하는 포멧으로 바꿔주는 HttpMessageConverter가 동작한다.
HttpEntity는 바디 정보를 편리하게 조회할 수 있는 객체이다.
-> 개선
http entity를 쓰는 것도 개선하여, requestbody가 제공된다. 이는 바디에서 데이터를 읽어서 문자로 바꿔버린다. HttpMessageConverter는 바디 데이터를 스트림으로 바이트 데이터를 받고 string으로 utf8로 바꾸는 것을 자동으로 해준다.
- Http 요청 메시지(json)
요청으로 넘어온 json 데이터를 객체로 만들기 위해서는 Jackson 라이브러리의 ObjectMapper가 필요하다.
스프링에서는 json이 넘어오면 객체로 받고 바인딩이 가능하다.
HttpEntity도 가능하며 HttpEntity는 http 메세지 전체를 다루는 개념이고 requestbody는 바디만 다루는 개념이다.
-> 응답
Http 메세지 컨버터는 응답에서도 적용된다. 문자나 객체를 컨버터에 의해서 텍스트나 json으로 바디에 넣어준다.
상태를 주고 싶으면 ResponseStatus를 주면 된다.
-> 동적인 응답 상태 변환
실무에서는 보통 ResponseEntity를 쓴다. 동적으로 응답 상태를 변환할 수 있다.
- HttpMessageConverter
son을 바디에서 직접 읽거나 응답 바디에 넣을 때 컨버터를 사용하면 편리하다. 안 그럼 스트림을 직접 다뤄야 한다.
문자 반환 : StringConverter
객체 반환 : JsonConverter
응답 시 톰켓이 컨트롤러를 호출하고 ResponseBody가 있으면, 뷰 리졸버 대신에 메세지 컨버터가 동작해서 String이나 Json으로 변환한다.
-> 스프링 MVC에서 컨버터 적용
1) 요청 : 컨트롤러를 호출하기 전에 @RequestBody이 있으면 바디에서 데이터를 꺼내서 동작
2) 응답 :@ResponseBody이 있으면 바디에 값을 write
컨버터는 인터페이스로 되어있고, 바디에서 데이터를 읽을 때와 쓸 때 모두 사용되며, read와 write 메서드를 가진다.
-> 순위
요청 : Content Type
응답 : Accept
미디어 타입을 체크해서 컨버터가 선택된다. 요청 시 Content Type을 보고 text면 String, Json이면 Jackson 컨버터가 작동한다. 응답 시에는 Accept를 보고 동일하게 동작한다.
- RequestMapping 핸들러 어댑터 구조
컨버터의 사용은 핸들러 어댑터와 관련이 있다.
-> 어댑터 동작 방식
핸들러 어댑터가 컨트롤러를 호출하는 구조에서 컨트롤러의 메서드에 매개변수로 들어오는 Model Attribute, Http Request, Model, RequestParam 등을 다 누군가 던져줘야 하는데 이를 알아보면 Http 메세지 컨버터 동작을 알 수 있다.
-> Argument Resolver
스프링 MVC에서는 컨트롤러의 메서드 매개변수에 큰 유연함을 보여준다. 이는 어댑터가 컨트롤러를 호출할 때 Argument 리졸버를 호출해서 컨트롤러가 필요로 하는 값을 다 생성하고 어댑터가 매개변수를 가지고 컨트롤러를 호출하기 때문이다.
스프링에는 30개가 넘는 리졸버가 있으며, 리졸버도 해당 파라미터를 생성할 수 있는 애인지 체크해서 support 하면 선택한다. 따라서 내 프로젝트에 맞는 리졸버를 만들어서 등록할 수도 있다. 스프링이 역할과 구현을 철저하게 설계해놨기 때문이다.
-> ReturnValueHandler
반환 시에는 ReturnValueHandler가 동작한다.
메세지 컨버터는 요청, 응답 때 둘 다 사용한다. 어댑터가 컨트롤러를 호출하는 과정에서 메세지 컨버터가 사용된다. 요청 시에는 리졸버가 파라미터를 컨트롤러 반환할 때 메세지 컨버터가 원하는 파라미터를 생성하고, 응답 시에는 컨버터가 원하는 포멧으로 데이터를 생성하고 리턴 벨류 핸들러가 Http 메세지 바디에 데이터를 넣는다.
Http 요청을 사용하지 않는 리졸버는 혼자서도 파라미터를 생성할 수 있는데 Http 메세지 컨버터를 사용하는 @RequestBody, HttpEntity 요청은 리졸버 중에서 컨버터를 사용해서 파라미터를 생성한다. HttpEntity 프로세서라는 리졸버가 support 메서드에서 HttpEntity가 있으면 “내가 처리할 수 있는 매개변수네”하고 리졸버로 동작하고
resolve 메서드에서 컨버터를 사용해서 HttpEntity 객체를 만들고 파라미터를 만들어서 반환한다.
read 메서드 내부에서 canRead 메서드로 메세지 바디에서 데이터를 읽을 수 있는 컨버터가 선택되고 read 메서드로 바디을 읽어서 원하는 포멧으로 생성 후 반환하면, 리졸버가 어댑터가 컨트롤러를 호출할 때 파라미터로 사용할 수 있도록 전달한다.
'[백엔드] > [spring | 학습기록]' 카테고리의 다른 글
[문법] 필터, 인터셉터 (0) | 2024.08.04 |
---|---|
[문법] 검증 (0) | 2024.08.04 |
[문법] Spring 핸들러 어댑터, API 설계 실전 (0) | 2024.08.02 |
[문법] 웹 서버와 서블릿 (0) | 2024.08.01 |
[문법] 빈 생명주기 콜백 (0) | 2024.08.01 |