๊ฐœ๋ฐœ/Spring Boot

HTTP Message Converter ์ด์•ผ๊ธฐ(1)

daramii 2022. 7. 7. 03:14

 

 

 


๋ทฐ ํ…œํ”Œ๋ฆฟ์œผ๋กœ HTML์„ ์ƒ์„ฑํ•ด์„œ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ,

HTTP API์ฒ˜๋Ÿผ JSON ๋ฐ์ดํ„ฐ๋ฅผ HTTP ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์—์„œ ์ง์ ‘ ์ฝ๊ฑฐ๋‚˜ ์“ฐ๋Š” ๊ฒฝ์šฐ HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•˜๋‹ค.

 

 

์Šคํ”„๋ง MVC๋Š” ๋‹ค์Œ์˜ ๊ฒฝ์šฐ์— HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์ ์šฉํ•œ๋‹ค.

HTTP ์š”์ฒญ : @RequestBody , HttpEntity(RequestEntity)
HTTP ์‘๋‹ต : @ResponseBody , HttpEntity(ResponseEntity) 

 

 

HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ ์ธํ„ฐํŽ˜์ด์Šค


org.springframework.http.converter.HttpMessageConverter

package org.springframework.http.converter;

  public interface HttpMessageConverter<T> {
  
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
    
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    
    List<MediaType> getSupportedMediaTypes();
    
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException;
            
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage
  outputMessage)throws IOException, HttpMessageNotWritableException;
  
}

 

HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋Š” HTTP ์š”์ฒญ, HTTP ์‘๋‹ต ๋‘˜ ๋‹ค ์‚ฌ์šฉ๋œ๋‹ค.

 

canRead() , canWrite() : ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค, ๋ฏธ๋””์–ดํƒ€์ž…์„ ์ง€์›ํ•˜๋Š”์ง€ ์ฒดํฌ
read(), write() : ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ๊ณ  ์“ฐ๋Š” ๊ธฐ๋Šฅ

 

 

 

์Šคํ”„๋ง ๋ถ€ํŠธ ๊ธฐ๋ณธ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ


์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ, ๋Œ€์ƒ ํด๋ž˜์Šค ํƒ€์ž…๊ณผ ๋ฏธ๋””์–ด ํƒ€์ž… ๋‘˜์„ ์ฒดํฌํ•ด์„œ ์‚ฌ์šฉ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ๋งŒ์•ฝ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋กœ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋„˜์–ด๊ฐ„๋‹ค.

(์ผ๋ถ€ ์ƒ๋žต)

  0 = ByteArrayHttpMessageConverter
  1 = StringHttpMessageConverter
  2 = MappingJackson2HttpMessageConverter
 
 

์œ„์˜ ๋ช‡๊ฐ€์ง€ ์ฃผ์š”ํ•œ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋“ค์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

ByteArrayHttpMessageConverter 
byte[] ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
ํด๋ž˜์Šค ํƒ€์ž…: byte[] , ๋ฏธ๋””์–ดํƒ€์ž…: */* ์š”์ฒญ
์˜ˆ) @RequestBody byte[] data ์‘๋‹ต
์˜ˆ) @ResponseBody return byte[] ์“ฐ๊ธฐ ๋ฏธ๋””์–ดํƒ€์ž… application/octet-stream

StringHttpMessageConverter
String ๋ฌธ์ž๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
ํด๋ž˜์Šค ํƒ€์ž…: String , ๋ฏธ๋””์–ดํƒ€์ž…: */* ์š”์ฒญ
์˜ˆ) @RequestBody String data ์‘๋‹ต
์˜ˆ) @ResponseBody return "ok" ์“ฐ๊ธฐ ๋ฏธ๋””์–ดํƒ€์ž… text/plain

MappingJackson2HttpMessageConverter
application/json
ํด๋ž˜์Šค ํƒ€์ž…: ๊ฐ์ฒด ๋˜๋Š” HashMap , ๋ฏธ๋””์–ดํƒ€์ž… application/json ๊ด€๋ จ์š”์ฒญ
์˜ˆ) @RequestBody HelloData data ์‘๋‹ต
์˜ˆ) @ResponseBody return helloData ์“ฐ๊ธฐ ๋ฏธ๋””์–ดํƒ€์ž… application/json ๊ด€๋ จ

 

์œ„์˜ ์ •์˜๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉฐ ์ดํ•ด ํ•ด๋ณด์ž.

 

 

StringHttpMessageConverter

// content-type: application/json
@RequestMapping
void hello(@RequetsBody String data) {}

๋จผ์ € ํด๋ž˜์Šค ํƒ€์ž…์€ String์ด๋‹ค. ๊ทธ๋Ÿผ 0์ˆœ์œ„๋ฅผ ์ง€๋‚˜ 1์ˆœ์œ„๋กœ ๋˜์–ด์žˆ๋Š” StringHttpMessageConverter๋กœ ๊ฐˆ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๊ณ ๋‚˜์„œ ํ•ด๋‹น ์ปจ๋ฒ„ํ„ฐ์˜ ๋ฏธ๋””์–ด ํƒ€์ž…์„ ํ™•์ธํ•ด๋ณด๋‹ˆ */* (๋ชจ๋“  ํƒ€์ž…์„ ํ—ˆ์šฉ) ์œผ๋กœ ๋˜์–ด ์žˆ๋‹ค. ์ฆ‰, content-type ์ด application/json์œผ๋กœ ๋˜์–ด ์žˆ๋Š” ํ•ด๋‹น ์š”์ฒญ์€ ํ—ˆ์šฉ์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ StringHttpMessageConverter๊ฐ€ ์‚ฌ์šฉ ๋จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

 

MappingJackson2HttpMessageConverter

//content-type: application/json
@RequestMapping
void hello(@RequetsBody HelloData data) {}

์ด๋ฒˆ์—๋Š” ํด๋ž˜์Šค ํƒ€์ž…์ด ๊ฐ์ฒด์ด๋‹ค. ๊ทธ๋Ÿผ 0์ˆœ์œ„๋ฅผ ์ง€๋‚˜๊ณ , ๋‹ค์‹œ 2์ˆœ์œ„๋„ ์ง€๋‚˜, ๋งˆ์ง€๋ง‰ 3์ˆœ์œ„ MappingJackson2HttpMessageConverter๋กœ ๊ฐ€๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ํ•ด๋‹น ์ปจ๋ฒ„ํ„ฐ์˜ ๋ฏธ๋””์–ด ํƒ€์ž…์€ application/json ๊ด€๋ จ์š”์ฒญ์ด๋ผ๊ณ  ์ ํ˜€ ์žˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ์—์„œ ์„ค์ •ํ•œ content-type๊ณผ ์ผ์น˜ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ MappingJackson2HttpMessageConverter ๊ฐ€ ์‚ฌ์šฉ ๋  ๊ฒƒ์ด๋‹ค.

 

 

???

//content-type: text/html
@RequestMapping
void hello(@RequetsBody HelloData data) {}

์ด๋ฒˆ์—๋„ ์—ญ์‹œ ๊ฐ์ฒด ํƒ€์ž…์ด๋‹ค. MappingJackson2HttpMessageConverter ๋กœ ๊ฐˆ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฏธ๋””์–ด ํƒ€์ž…์ด application/json ๊ด€๋ จ์š”์ฒญ์ด์–ด์•ผ ํ•˜๋Š”๋ฐ, ์œ„์˜ ์ฝ”๋“œ์—์„œ๋Š” text/html ํƒ€์ž…์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์ƒํ™ฉ์€ ํƒˆ๋ฝ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

 

 

HTTP ์š”์ฒญ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ


1. HTTP ์š”์ฒญ์ด ์˜ค๊ณ , ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @RequestBody , HttpEntity ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

2. ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด canRead() ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

     : (1) ๋Œ€์ƒ ํด๋ž˜์Šค ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š”๊ฐ€.
            ์˜ˆ) @RequestBody ์˜ ๋Œ€์ƒ ํด๋ž˜์Šค ( byte[] , String , HelloData )

       (2) HTTP ์š”์ฒญ์˜ Content-Type ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š”๊ฐ€.

            ์˜ˆ) text/plain , application/json , */*

 

3. canRead() ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด read() ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ณ , ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

 

 

HTTP ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ƒ์„ฑ


1. ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @ResponseBody , HttpEntity ๋กœ ๊ฐ’์ด ๋ฐ˜ํ™˜๋œ๋‹ค.


2. ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด canWrite() ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

    : (1) ๋Œ€์ƒ ํด๋ž˜์Šค ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š”๊ฐ€.
           ์˜ˆ) return์˜ ๋Œ€์ƒ ํด๋ž˜์Šค ( byte[] , String , HelloData )

      (2) HTTP ์š”์ฒญ์˜ Accept ๋ฏธ๋””์–ด ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š”๊ฐ€.

          (๋” ์ •ํ™•ํžˆ๋Š” @RequestMapping ์˜ produces )

           ์˜ˆ) text/plain , application/json , */*

 

3. canWrite() ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด write() ๋ฅผ ํ˜ธ์ถœํ•ด์„œ HTTP ์‘๋‹ต ๋ฉ”์‹œ์ง€ ๋ฐ”๋””์— ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.