🤗이 글은 "스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술" 김영한님 강의를 듣고 작성하였습니다.
스프링 웹 개발 기초
1. 정적 컨텐츠
그냥 파일을 그대로 내려준다.
spring에서 정적 파일은 main/resources/static 폴더에 작성한다.
- 브라우저에서 /hello-static.html 을 요청받으면 톰켓 내장서버에서 인식한다.
- 스프링 컨테이너의 Controller에서 hello-static으로 mapping된 파일이 있는지 찾아본다. --> MVC에서 자세히
- mapping된 것이 없으면 static폴더 하위에 있는 hello-static.html 파일을 찾아 클라이언트로 전송한다. (여기서도 없으면 오류가 나는거지)
2. MVC 템플릿 엔진
템플릿 엔진을 '모델-뷰-컨트롤러' 방식으로 쪼개서 템플릿 엔진으로 랜더링 된 html을 클라이언트에게 전달해 준다.
과거에는 JSP안에 모든 로직을 처리하는 model1 방식을 사용했다. 하지만 이 방식은 view 파일 안에 모든 로직이 담겨있어서 유지보수가 매우 떨어지고, 역할의 분할이 되지 않는 구식 방법이다. 처음 장고를 썼을 때 이랬던 것 같다.
최근엔 MVC로 분리하여 구현한다.
머릿속을 더듬어 2년 전 과제로 MVC 패턴을 배웠던 것을 기억해냈다. 이때도 꽤나 이해하려고 열심히 찾아 본 것 같은데 다 까먹었다. 다시 읽어보니 내 이해를 바탕으로 풀어서 그런지 읽기 쉽다.
예제를 통해 spring에서 MVC와 템플릿 엔진이 어떻게 사용되는지 확인해보자.
View (hello-template.html)
spring에서 템플릿 파일은 main/resources/template 폴더에 작성한다.
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
Controller (helloController)
spring에서 컨트롤러는 main/java 폴더 하위에 있는 hello.hellospring(프로젝트명) 패키지에 service 패키지를 만들고 그 안에서 컨트롤러 클래스를 작성한다.
@Controller
public class HelloController {
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
}
컨트롤러에서 hello-mvc와 mapping이 되어있다. 이 때 다음과 같이 동작한다.
- 사용자가 /hello-mvc를 요청하면 톰캣 서버에서 요청을 인지한다.
- 스프린 컨테이너 내부의 helloController가 mapping된 매서드가 있는지 찾는다. 여기서는 helloMvc()가 mapping되어 존재한다.
- helloMvc()에서 @RequestParam을 통해 데이터(?name=spring!!)를 가공한다(클라이언트의 요청 처리).
- 인수로 query문으로 파싱한 데이터(spring!!)가 넘어온다. 그 정보는 name라는 변수에 담긴다.
- model에 {"name" : name}이라는 key:value 쌍으로 저장한다.
- controller는 가공한 데이터와 view페이지의 정보(hello-template)를 담은 Model객체와 View객체를 반환한다.
- 이 반환값을 viewResolver가 받아서 templates하위에 있는 hello-template.html을 찾는다. 템플릿 안에서 사용되는 키를 찾아 값을 넣어준 뒤 html로 변환하여 반환한다.
여기서 모델(model)은 애플리케이션의 데이터(데이타베이스, 처음의 정의하는 상수, 초기화값, 변수 등)를 뜻한다. 또한 이 데이터들의 가공하는 컴포넌트를 포함한다.
3. API
보통 일반적인 스프링의 api방식은 객체를 반환하는 것.
MappingJakson2HttpMessageConverter를 통해서 json스타일로 바꿔서 반환해준다.
뷰 이런거 없이 바로 html response에 반환해주는 것
API를 사용하면 뷰 없이 요청받은 데이터를 (문자 또는 객체의 형태로)바로 html에 내보낼 수 있다. 예제를 보자.
@ResponseBody 문자 반환
@Controller
public class HelloController {
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
}
- @ResponseBody : HTML BODY에 문자 내용을 직접 반환
- 결과
@ResponseBody 객체 반환
@Controller
public class HelloController {
static class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
}
- @ResponseBody를 사용하고 객체를 반환하면 JSON으로 변환됨
- 결과
그림으로 보면 이렇다.
1, 2, 3은 MVC와 동일
4. @RespinseBody가 있으면 controller는 HttpMessageConverter에게 데이터를 반환한다.
5. HttpMessageConverter가 받은 값이 객체이면 JSON형태, 객체가 아니면 String 형태로 변환하여 바로 브라우저에 전송한다.
- @ResponseBody를 사용하면 viewResolver 대신에 HttpMessageConverter 가 동작
- 기본 문자처리: StringHttpMessageConverter
- 기본 객체처리: MappingJackson2HttpMessageConverter
- byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음