스프링 웹을 개발하는 방법은 여러 가지가 있다.
- 정적 콘텐츠
- 파일을 웹 브라우저에 그대로 내려주는 것. - MVC와 템플릿 엔진
- 가장 많이 개발하는 방식
- html을 그대로 내리는 것이 아니라 서버에서 동적으로 바꿔서 내리는 것.
- Model, View, Controller - API
- 데이터 포맷으로 client에게 전달하는 방식
정적 콘텐츠 (Static Content)
스프링 부트는 정적 콘텐츠를 기본으로 제공한다.
정적 콘텐츠 생성하기
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
resource/static 에 hello-static.html 파일을 생성한다.
주소창에 localhost:8080/hello-static.html 입력면 위와 같은 화면을 볼 수 있다.
동작 방식
웹 브라우저에서 localhost:8080/hello-static.html을 입력하면
내장 톰캣 서버가 요청을 받아서 스프링 컨테이너로 전달한다.
스프링 컨테이너가 hello-static 컨트롤러가 있는지 찾는다.
-> 컨트롤러가 우선순위를 갖는다.
관련된 컨트롤러가 없으면 톰캣 서버가 resources/static에서 hello-static.html을 view로 응답한다.
MVC와 템플릿 엔진
MVC : Model, View, Controller
과거에는 컨트롤러와 뷰가 분리되지 않고 뷰에서 모든 것을 개발했다. -> 모델 1 방식
현재는 MVC방식으로 많이 개발한다.
뷰는 화면을 구성하는 데 모든 역량을 집중해야 하고
컨트롤러는 비즈니스 로직과 관련되거나 내부적으로 처리해야 하는 개발에 집중해야 한다.
컨트롤러에서 모델에 관련된 것들을 담아 화면에 넘겨주는 패턴을 많이 사용한다.
효율적으로 개발하기 위해서 Model, View, Controller를 나누는 것이 기본이다.
MVC 동작
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class HelloController {
@GetMapping("hello")
public String hello(Model model){
model.addAttribute("data","spring!!");
return "hello";
}
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
}
main/java에 HTTP 요청을 받을 controller 패키지를 만든다.
controller패키지에 HelloController 클래스를 생성한다.
<!-- hello-template.html -->
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
resources/templates 폴더에 hello-template.html을 만든다.
템플릿 엔진으로 작동하면 hello! empty이 'hello ' + ${name} 내용으로 치환된다.
브라우저에서 localhost:8080/hello-mvc으로 들어가면 에러 페이지가 나온다.
WARN 12196 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver :
Resolved [org.springframework.web.bind.MissingServletRequestParameterException:
Required request parameter 'name' for method parameter type String is not present]
로그를 보면 위와 같은 메시지가 나온다. name parameter가 없어서 에러가 발생한 것이다.
RequestParam( )에 값을 넣어줘야 한다.
required()의 default 값은 true이기 때문에 그대로 넘겨주고 주소창에 parameter를 입력한다.
localhost:8080/hello-mvc?name=spring!!!
name으로 spring!!!을 helloMvc 메서드에 넘겨주었다.
HTTP GET방식으로 parameter를 넘겨줄 수 있다.
동작 원리
name=spring!!!으로 넘어가면 컨트롤러에서
name이 spring!!!으로 바뀌고 attributeName인 name도 spring!!!으로 바뀐다.
그 결과 모델에 담기게 되고 hello-template으로 넘어가면
$로 표시된 것이 모델의 키 값인 것 중 꺼내서 치환해준다.
그렇게 해서 hello spring!!!으로 화면에 출력된다.
웹 브라우저에서 localhost:8080/hello-mvc 호출 -> 내장 톰캣 서버 -> 스프링
helloController에 매핑이 되어 있으므로 호출 return : hello-template, model(name : spring)으로 넘겨줌.
viewResolver로 넘겨준다. 화면과 관련된 해결자가 동작한다. 뷰를 찾아주고 연결시켜주는 역할.
viewResolver가 templates/hello-template.html helloController의 return 값과 같은 것을 찾아서
thymleaf 템플릿 엔진으로 처리를 요청한다. 템플릿 엔진이 렌더링 하여 변환한 html을 넘겨준다.
API
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
@ResponseBody의 의미는 HTTP에서 body의 데이터를 직접 넣어주겠다는 뜻.
데이터를 그대로 내려준다.
API 동작
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
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;
}
}
hello라는 객체를 return.
이와 같이 key와 value로 이루어진 것이 json.
key : value
과거에는 xml방식이 많이 쓰였지만, 무겁고 태그를 열고 닫고 두 번 써야 한다.
최근에는 json방식으로 통일되었다.
객체를 반환하고 @ResponseBody라고 해놓으면 json으로 반환하는 것이 기본이다.
동작 원리
웹 브라우저에서 localhost:8080/hello-api 호출 -> 내장 톰캣 서버 -> 스프링에서 hello-api확인
-> @ResponseBody가 있다. -> HTTP 응답에 그대로 데이터를 넘김. -> 그런데 객체 반환
-> default가 json방식으로 데이터를 만들어서 HTPP에 반환 -> HttpMessageConverter 동작
-> 단순 문자면 StringConverter 동작, 객체면 JsonConverter 동작 -> hello 객체를 json방식으로 바꾼다
-> json이 서버에 응답.
@ResponseBody 사용
- HTTP의 BODY에 문자 내용을 직접 반환
- viewResolver 대신에 HttpMessageConverter가 동작
- 기본 문자 처리 : StringHttpMessageConverter
- 기본 객체 처리 : MappingJackson2HttpMessageConverter
- byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음
- 정적 콘텐츠
파일을 그대로 내려준다.
- MVC와 템플릿 엔진
템플릿 엔진을 Model, View, Controller로 나누어 View를 템플릿 엔진으로 프로그래밍한 html을 렌더링이 된 html을 client에 전달한다.
- API
스프링 개발할 때 일반적으로 말하는 것은 객체 전달.
httpMessageConverter를 통해 json으로 변환해서 반환해주는 것.
view 없이 http response에 값을 넣어 반환해 주는 것이 @ResponseBody 방식