8. 스프링 Http 응답

김현준·2023년 7월 28일

Gaounuri_Spring_Study

목록 보기
9/10

Project Code File

📌 목차

  • HTTP 응답 - 정적 리소스, 뷰 템플릿
  • HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
  • HTTP 메시지 컨버터
  • 요청 매핑 헨들러 어뎁터 구조

📌 HTTP 응답 - 정적 리소스, 뷰 템플릿

HTTP 응답에는 크게 3가지가 존재한다.

  1. 정적 리소스 ex) HTML , CSS , JS

  2. 뷰 템플릿 ex) 동적인 웹 브라우저

  3. HTTP 메세지 ex) HTTP 메시지 바디에 json 형식 데이터

/static , /public , /resources , /META-INF/resources

스프링에서 정적 리소스 파일을 보관할때 위 경로에서 저장해야한다.

src/main/resources/templates

또한 스프링에서는 기본적인 뷰 템플릿 경로는 위와 같다.

package hello.springmvc.basic.response;

@Controller
public class ResponseViewController {

    @RequestMapping("/response-view-v1")
    public ModelAndView responseViewV1() {
        ModelAndView mav = new ModelAndView("response/hello").addObject("data", "hello!");

        return mav;
    }

    @RequestMapping("/response-view-v2")
    public String responseViewV2(Model model) {
        model.addAttribute("data", "hello!");
        return "response/hello";
    }

    @RequestMapping("/response/hello")
    public void responseViewV3(Model model) {
        model.addAttribute("data", "hello!");
    }
}

@ResponseBody 가 없으면 response/hello 로 뷰 리졸버가 실행되어 뷰를 찾고 렌더링 한다.

ModelAndView 객체에 경로를 저장할 수 있고
String 형식으로 경로를 반환할 수 있다.
void 반환할시 요청 URL 을 사용한다. 하지만 이는 명시성이 떨어진다.

📌 HTTP 응답 - HTTP API, 메시지 바디에 직접 입력

HTTP API 를 제공하는 경우에는 HTML 이 아니라 데이터를 전달해야 하므로 HTML 메시지 바디에 json 같은 형식의 데이터를 저장해야한다.

package hello.springmvc.basic.response;

@Slf4j
@Controller
public class ResponseBodyController {

    @GetMapping("response-body-string-v1")
    public void responseBodyV1(HttpServletResponse response) throws IOException {
        response.getWriter().write("ok");
    }
}

가장 기본적인 방식은 HttpServletResponse 를 통해 응답하는 방법이 있다.

@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() throws IOException {
    return new ResponseEntity<>("ok", HttpStatus.OK);
}

ResponseEntity 엔티티는 HttpEntity 를 상속 받았는데, HttpEntityHTTP 메시지의 헤더, 바디
정보를 가지고 있다. ResponseEntity 는 여기에 더해서 HTTP 응답 코드를 설정할 수 있다.

@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
    return "ok";
}

@ResponseBody 에노테이션을 쓰면 뷰를 사용하지 않고 HTTP 메시지 컨버터를 통해서 HTTP 메시지를 직접 입력할 수 있다.

@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
    HelloData helloData = new HelloData();
    helloData.setUsername("userA");
    helloData.setAge(20);
    return new ResponseEntity<>(helloData, HttpStatus.OK);
}

ResponseEntity 를 사용하면 JSON 형식의 데이터를 반환한다.
상태코드도 지정 가능하다.

@ResponseStatus(HttpStatus.OK) 같은 에노테이션을 통해서도 상태코드를 설정할 수 있다.

📌 HTTP 메시지 컨버터

HTTP API 처럼 json 형식의 데이터를 HTTP 메시지 바디에서 직접 읽거나 쓰는 경우 HTTP 메시지 컨버터를 사용하면 편리하다.

스프링 부트는 몇가지 주요한 메시지 컨버터를 제공한다.

  • 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 관련

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

만약 위와같은 코드가 실행된다면 StringHttpMessageConverter 이 실행된다.

content-type: application/json
@RequestMappingvoid 
hello(@RequestBody HelloData data) {}

위와 같은 코드가 실행되면 MappingJackson2HttpMessageConverter 이 실행된다.

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

마지막으로 위 코드는 실행되지 않는다. application/json 형식이 아니기 때문이다.

📌 요청 매핑 헨들러 어뎁터 구조

image

이전에 위와같은 스프링 MVC 패턴 구조를 살펴보았다.
지금까지 알아본 HTTP 메시지 컨버터는 어디쯤에 있을까?

바로 @RequestMapping 을 처리하는 핸들러 어뎁터인 요청 매핑 핸들러 어뎁터 RequestMappingHandlerAdapter 에 있다.

image

이전에 요청과 응답에서 패밍을 할때 파라미터에 HttpServletRequest , Model , @RequestParam , @ModelAttirbute , @RequestBody , HttpEntity 같은 많은 파라미터를 사용했다.

이렇게 유연하게 파라미터를 처리할 수 있는 이유가 바로 ArgumentResolver 덕분이다.

ArgumentResolver 가 해당 파라미터를 지원하는지 체크하고 가능한 핸들러가 객체를 생성해 컨트롤러에게 전달해준다.

ReturnValueHandle 는 컨트롤러에서 String 으로 뷰 이름을 반환해도 동작하게 하도록 지원해준다.

image

요청의 경우 @RequestBody 를 처리하는 ArgumentResolver 가 있고 HttpEntity 를 처리하는 ArgumentResolver 가 있다. 이 ArgumentResolver 들이 HTTP 메시지 컨버터를 사용해도 필요한 객체를 사용한다.

응답의 경우 @ResponseBodyHttpEntity 를 처리하는 ReturnValueHandler 가 있다. ReturnValueHandlerHTTP 메시지 컨버터를 호출해서 응답 결과를 만들어 준다.

profile
울산대학교 IT융합학부

0개의 댓글