HTTP 응답 데이터를 만드는 방법으로 다음 3가지 방법이 있다.
1. 정적 리소스
ex, 웹 브라우저에 정적인 HTML, css, js를 제공할 때, 정적 리소스를 사용한다.
2. 뷰 템플릿 사용
ex, 웹 브라우저에 동적인 HTML을 제공할 때, 뷰 템플릿을 사용한다.
3. HTTP 메시지 사용
HTTP API를 제공하는 경우에는 HTML이 아닌 데이터를 전달해야 하므로, HTTP 메시지 바디에 JSON 같은 형식으로 데이터를 담아 보낸다.
정적 리소스는 해당 파일을 변경 없이 그대로 서비스하는 것이다.
스프링부트는 클래스패스의 다음 디렉토리에 있는 정적 리소스로 서비스를 제공한다.
/static
, /public
, /resources
, /META-INF-resources
따라서 만약 HTML 파일이 다음과 같은 경로에 들어 있으면,
src/main/resources/static/basic/hello-form.html
웹 브라우저에서 다음과 같이 실행하면 된다.
http://localhost:8080/basic/hello-form.html
뷰 템플릿을 거쳐서 html이 생성되고, 뷰가 응답을 만들어서 전달한다.
스프링부트는 기본 뷰 템플릿 경로를 다음으로 제공한다.
src/main/resources/templates
예를 들어 다음 경로에 뷰 템플릿 생성하는 경우를 살펴보자.
src/main/resources/templates/response/hello.html
@Controller
public class ResponseViewController {
@RequestMapping("/response-view")
public String responseViewV2(Model model) {
model.addAttribute("data", "hello!");
return "response/hello";
}
}
@Controller
애노테이션이 붙어있고, 컨트롤러가 String을 반환하는 경우, return 값으로 뷰 리졸버가 실행되어 뷰를 찾고 렌더링 된다. (@ResponseBody
가 있으면 뷰 리졸버를 실행하지 않고 HTTP 메시지 바디에 직접 return 값이 입력된다.)
HTML이나 뷰 템플릿을 사용해도 HTTP 응답 메시지 바디에 HTML 데이터가 담겨서 전달된다. 그러나 여기서 설명하는 내용은 정적 리소스나 뷰 템플릿을 거치지 않고, 직접 HTTP 응답 메시지를 전달하는 경우를 말한다.
@Slf4j
@Controller
public class ResponseBodyController {
@GetMapping("/response-body-string-v1")
public void responseBodyV1(HttpServletResponse response) throws IOException {
response.getWriter.write("ok");
}
@GetMapping("/response-body-string-v2")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("ok", HttpStatus.OK);
}
@ResponseBody
@GetMapping("/response-body-string-v3")
public String responseBodyV3() {
return "ok";
}
}
response.getWriter.write("ok")
return new ResponseEntity<>("ok", HttpStatus.OK)
ResponseEntity
로 응답 메시지를 생성하는 경우에 HttpStatus.OK
와 같이 상태 코드를 함께 전달할 수 있다.
@ResponseBody
@ResponseBody
애노테이션을 붙이고, String으로 반환하면 return 값이 그대로 응답 메시지로 전달된다.
@Slf4j
@Controller
public class ResponseBodyController {
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
Hellodata data = new HelloData();
data.setUsername("userA");
data.setAge(20);
return new ResponseEntity<>(data, HttpStatus.OK);
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
Hellodata data = new HelloData();
data.setUsername("userA");
data.setAge(20);
return data;
}
}
return new ResponseEntity<>(data, HttpStatus.OK)
텍스트 형식과 다르게 객체를 응답 메시지로 전달할 수 있다.
@ResponseBody
, @ResponseStatus()
@ResponseBody
를 통해 객체를 그대로 반환할 수 있다.(return data
)
그리고 @ResponseStatus
을 사용하여 상태 코드도 함께 전달할 수 있다.
각 메소드마다 @ResponseBody
를 붙이는 게 번거로울 때 클래스 레벨에 @ResponseBody
를 붙이면 모든 메소드에 대해 적용된다.
@RestController
내부에는 @Controller
와 @ResponseBody
가 들어있다. 따라서 @Controller
+@ResponseBody
대신에@RestController
를 사용해도 같다.