웹 개발 방식 3가지
- 정적 컨텐츠
- MVC와 템플릿 엔진
- API
📝 정적 컨텐츠
정적 컨텐츠
스프링 부트는 정적 컨텐츠 기능을 자동으로 제공한다. Spring Boot Features
정적 컨텐츠 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>
resources/static/hello-static.html
정적 컨텐츠 동작 원리
- 스프링은 가장 먼저 controller에서
hello-static
이 있는지 찾는다. 이때, controller가 먼저 우선순위를 갖는다 - 없으면
resources/static
에서 hello-static을 찾는다. <정적 컨텐츠>
📝 MVC와 템플릿 엔진
MVC
- Model, View, Controller
- 관심사 분리가 목적!
- 사용자가 controller를 조작하면 controller는 model을 통해서 데이터를 가져온다. 그리고 이 정보를 바탕으로 시각적인 표현을 담당하는 View를 제어해서 사용자에게 전달하게 된다.
HelloController.java
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
java/hello/hellospring/controller/HelloController.java
- @RequestParam("name") 로 외부(웹)에서 파라미터를 받아온다. 이전에는 문자열 “hello!!” 을 직접 넘겨줬는데, 이번에는 외부에서 파라미터를 받아온다는 점에서 다르다.
- model.addAttribute("name", name); 파라미터로 넘어온 name을 넘긴다.
- 이때 "name" 이 key이고, name이 String name 의 name이다.
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
- 타임리프 템플릿의 장점은 서버 없이 html 정적 파일을 열어봐도 구조를 알 수 있다는 점이다.
- 즉, hello! empty 는 서버가 동작하지 않을 때 보여지는 내용이다.
서버가 동작하는 경우 (템플릿 엔진 동작) → ${name} 내용이 전달받은 값으로 치환됨
서버가 동작하지 않는 경우 (파일 경로로 직접 들어가는 경우)
에러가 남! 에러가 나면 일단 로그를 확인해야 한다.
2023-07-14 15:30:45.915 WARN 888 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'name' for method parameter type String is not present]
WARN warning이 뜬 것을 확인할 수 있다.
Required request parameter 'name' for method parameter type String is not present 기본으로 name 파라미터를 넘겨야 하는데, http://localhost:8080/hello-mvc 로 name을 넘기지 않았기 때문에 발생한 에러이다.
잘 동작하는 것을 확인할 수 있다.
MVC, 템플릿 엔진 동작 원리
📝 API
정적 컨텐츠를 제외하면 2가지만 기억하면 된다.
- HTML로 내리는지
- API 방식으로 데이터를 바로 내리는지
HelloController.java
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
java/hello/hellospring/controller/HelloController.java
@ResponseBody 의 의미
- html의 body 태그 아님
- http의 head부와 body부 중 응답 body부에 "hello " + name 데이터를 직접 넣어주겠다는 의미이다. 이 문자가 요청한 client에 그대로 넘어감!
- 웹 템플릿 엔진과의 차이는 view가 없다는 것이다.
웹 템플릿 엔진과 API의 차이
hello-string 즉, API의 페이지 소스를 보면 html 태그 전혀 없이 그냥 적은 문자열만 있음
- 템플릿 엔진 : 화면을 가지고 view라는 템플릿을 조작하는 방식
- API : 데이터를 그대로 내려주는 방식
→ 하지만 문자만 사용하는 이 예시는 사실 잘 쓰지 않음. 문자 대신 데이터를 사용하는 경우가 중요!
HelloController.java
@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;
}
}
java/hello/hellospring/controller/HelloController.java
return hello; 으로 문자가 아닌 데이터를 넘기는 경우
→ {"name":"spring"} JSON 방식으로 표현된다!
@ResponseBody 문자 반환
@ResponseBody 를 사용하면 뷰 리졸버( viewResolver )를 사용하지 않음
대신에 HTTP의 BODY에 문자 내용을 직접 반환(HTML BODY TAG를 말하는 것이 아님)
@ResponseBody 객체 반환
ResponseBody 를 사용하고, 객체를 반환하면 객체가 JSON으로 변환됨
@ResponseBody 동작 원리
@ResponseBody 를 사용하는 경우
- HTTP의 BODY에 문자 내용을 직접 반환
- viewResolver 대신에 HttpMessageConverter가 동작
- 반환된 것에 따라 다르게 처리
- 기본 문자 처리: StringHttpMessageConverter
- 기본 객체 처리: MappingJackson2HttpMessageConverter
→ JSON 방식으로 만들어서 HTTP 응답에 반환하는 게 기본 정책이다.
→ 객체를 JSON으로 바꾸는 유명한 라이브러리에 Jackson 과 GSON 이 있는데, 스프링은 이 중 Jackson 을 기본으로 탑재하도록 했다. - byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음