1. 정적 컨텐츠
정적 컨텐츠는 만들어진 파일 그대로 사용자에게 전달된다.
- 기본적으로 스프링 부트는 정적 컨텐츠를 /static (/public, /resources, /META-INF/resources)에서 제공한다.
- 스프링 부트 매뉴얼 : https://docs.spring.io/spring-boot/docs/2.7.8/reference/htmlsingle/#web.reactive.webflux.static-content
- resources/static/hello-static.html
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
- 실행 : http://localhost:8081/hello-static.html
정적 컨텐츠 이미지
- /hello-static.html 요청을 받고, 내장 톰캣 서버는 컨트롤러에서 hello-static을 찾는다.
- 컨트롤러가 없는 경우, resources에서 파일을 찾고 반환한다.
2. MVC와 템플릿 엔진
MVC : Model, View, Controller
Controller
- java/hello.hellospring/controller/HelloController
@GetMapping("hello-mvc")
// 이 메서드는 웹사이트에서 url을 파라미터로 받아오도록 해준다.
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
- http://localhost:8081/hello-mvc만 입력하면 오류페이지가 뜬다.
- 파라미터로 값을 넘겨주어야 하므로 http://localhost:8081/hello-mvc
?name=spring화이팅과 같이 해주어야 한다.
View
- resources/template/hello-template.html
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
- 실행 : http://localhost:8081/hello-mvc?name=spring화이팅
MVC, 템플릿 엔진 이미지
- 내장 톰캣 서버는 컨트롤러에서 Get으로 매핑된 hello-mvc 메서드를 찾아 실행시킨다.
- 파라미터로 받은 name을 Model에 담고, hello-template으로 리턴한다.
- 뷰리졸버에서 리턴된 hello-template와 대응되는 templates의 html을 찾아 처리한다.
3. API
정적 컨텐츠를 제외하면, html 방식으로 보낼지, API 방식으로 데이터만을 바로 보낼지 2가지 방식이 있다.
1. MVC 방식
원하는 view를 찾은 후, 템플릿 엔진을 통해서 해당 view를 html로 렌더링 해서 웹 브라우저에게 넘겨주는 방식
2. API 방식
JSON 형식으로 바꾸어 클라이언트에게 데이터를 전달하는 방식. view 없이 그대로 HTTP의 body에 전달하는 방식
- Template engine은 view라는 템플릿이 있는 상황에서 view를 html로 변환하는 것이고, API는 데이터를 그대로 내보내는 것이다.
@ResponseBody 문자 반환
- java/hello.hellospring/controller/HelloController.java
@GetMapping("hello-string")
@ResponseBody // HTTP body부에 데이터를 "직접" 넣어주겠다
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
@ResponseBody를 사용하면 뷰 리졸버(viewResolver)를 사용하지 않는다.- 대신에 HTTP의 body에 문자 내용을 직접 반환한다. (HTML body tag를 말하는 것이 아니다.)
- 요청한 주소의 페이지 소스를 보면 html 코드가 존재하지 않고 데이터만 존재한다.
- 실행 : http://localhost:8081/hello-string?name=spring
@ResponseBody 객체 반환
- java/hello.hellospring/controller/HelloController.java
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) { // 객체가 오면 > json 반환
Hello hello = new Hello();
hello.setName(name);
return hello; // 객체를 넘겨줌
}
static class Hello { // 객체
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@ResponseBody를 사용하고, 객체를 반환하면 객체가 Json으로 변환된다.- 실행 : http://localhost:8081/hello-api?name=spring
@ResponseBody 사용 원리
- 내장 톰캣 서버가 컨트롤러에서 hello-api 메서드를 찾고, 템플릿 엔진의 경우 viewResolver로 넘겨주지만, @ResponseBody가 붙여진 api의 경우 HTTP의 body에 그대로 입력하여 반환한다.
- 반환되는 것이 객체이므로, Json 형태로 만들어서 HTTP에 반환되도록 한다.
@ResponseBody 사용
- HTTP의 body에 문자 내용을 직접 반환
- viewResolver 대신에
HttpMessageConverter가 동작 - 기본 문자처리 : StringHttpMessageConverter (string 컨버터)
- 기본 객체처리 : MappingJackson2HttpMessageConverter (json 컨버터)
- byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있다.
💬 클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합하여 HttpMessageConverter가 선택된다.