[spring] HTTP 응답

공수정·2022년 5월 29일
0

spring

목록 보기
28/32
post-custom-banner

종류

spring에서 만들 수 있는 응답 데이터는 크게 3종류로 나누어져 있다.
각 응답 데이터를 어떻게 만들어서 응답하는지에 대해 정리해보고자 한다.

1. 정적 리소스

정적 리소스 : js, css, images 등과 같이 변화가 없는 리소스를 의미

2. 뷰 템플릿

동적인 html을 리턴할 때에는 뷰 템플릿을 이용한다.

3. HTTP 메시지

HTTP API를 작성 할 때에는 html이 아니라 데이터를 전달해야해서 HTTP 메시지에 JSON과 같은 데이터를 실어보낼수 있도록 한다.


1. 정적 리소스

기본경로

정적 리소스는 spring에서 코드를 따로 작성해서 응답을 하는 것이 아니라, 정적 리소스들을 미리 약속된 디렉토리에 넣어놓으면 알아서 spring이 정적 리소스를 제공한다.
이 때 미리 약속된 디렉토리는 클래스 패스의 시작 경로인 src/main/resources안에 있는 /static , /public , /resources , /META-INF/resources 이 있다.

ex src/main/resources/static/jsexample.js가 있다면,
/js/example.js를 요청하면 된다.


2. 뷰 템플릿

기본경로

뷰 템플릿을 거쳐서html을 생성하고, 뷰가 응답을 만들어서 전달한다.
이때 spring은 뷰 템플릿 기본 경로를 제공하는데 변경도 가능하다.
기본 경로는 src/main/resources/templates 이곳이다.

컨트롤러 작성

뷰 템플릿은 컨트롤러에서 리턴하는 방식이 3가지 정도가 있다.
각 방식의 특징에 대해서 알아보자

1) ModelAndView

이 방식은 컨트롤러 내에서 ModelAndView를 생성해서 반환하는 방법이다.
생성할 때에 경로를 넣고, 만약 같이 보내야할 데이터가 있다면 생성된 ModelAndView에 데이터를 추가해서 같이 전송한다.

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

2) String

이 방식은 보내야할 데이터가 있다면 model에 데이터를 넣고, 리턴은 경로만 리턴을 하는 방식이다. 앞에 ModelAndView와 기능은 같은데 ModelAndView를 직접 만들지 않아도 되서 코드가 훨씬 깔끔하다.

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

3) Void

이 방식은 앞의 String을 리턴하는 방식과 비슷한데, return을 void로 처리한 방식이다.
이것은 RequestMapping되는 경로와 뷰 템플릿의 경로가 같으면 사용할 수 있는데, 이 방식은 명시적이지 않아서 추천하지 않는다.

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

3. HTTP 메시지

이번에는 HTTP API를 제공하는 경우 html이나 뷰 템플릿이 아닌 데이터를 응답으로 보내야하기 때문에 HTTP 메시지에 데이터를 넣어야한다.

물론 정적 리소스, 뷰 템플릿을 사용해도 HTTP 메시지에 최종 데이터가 담겨서 가지만, 정적 리소스는 동적인 데이터를 전송할 수 없고, 뷰 템플릿은 뷰 템플릿을 거쳐서 가야한다. 이렇게 정적 리소스나 뷰 템플릿을 거치지 않고 직접 HTTP 응답 메시지를 전달하는 경우를 알아 보려고 한다.

컨트롤러 작성

1) HttpServletResponse

Servlet을 사용할 때 처럼 HttpServletResponse를 통해서 직접 전달하는 방식이다.

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

2) ResponseEntity

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

HttpStatus는 HTTP 응답 코드가 정의 되어있다.
전부 상수로 되어있는데 200이라고 적는 것보다 HttpStatus.OK라고 적는 것이 보기에 좀 더 직관적이라 사용한다.

  • string

@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
	return new ResponseEntity<>("ok", HttpStatus.OK);
}
  • json 등의 객체타입
@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);
}

3) @ResponseBody

@ResponseBody어노테이션을 사용하면 리턴 값이 그대로 들어간다.
따로 생성을 하거나 하지 않기 때문에 코드가 가장 간결하다.

HTTP 응답 코드도 설정할 수 있는데, @ResponseStatus(HttpStatus.OK)를 사용해서 할 수 있다.
다만 위의 ResponseEntity방식처럼 동적으로 지정할 수는 없어서 동적으로 지정하고 싶다면 ResponseEntity을 사용해서 리턴시켜야한다.

  • string
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
	return "ok";
}
  • json 등의 객체타입
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
	HelloData helloData = new HelloData();
	helloData.setUsername("userA");
	helloData.setAge(20);
	return helloData;
}

ResponseEntity엔티티나 @ResponseBody어노테이션을 사용해서 객체 타입의 데이터를 데이터로 보낸다면 HTTP 메시지 컨버터가 동작해서 JSON 형식으로 변환된다.

출처
1. 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

profile
계속해서 공부하는 개발자입니다 :)
post-custom-banner

0개의 댓글