๐ฎ GitHub ๋ฐ๋ก๊ฐ๊ธฐ
๐ Spring MVC
: MVC (Model - View - Controller) ์ํํธ์จ์ด ๋์์ธํจํด
Layer | ์ญํ |
---|---|
Model | ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ณด ๋ฐ ๋ฐ์ดํฐ |
View | ํ ์คํธ, ์ฒดํฌ๋ฐ์ค ๋ฑ ์ฌ์ฉ์์ธํฐํ์ด์ค ์์ |
Controller | ๋ฐ์ดํฐ์ ๋น์ฆ๋์ค๋ก์ง ์ฌ์ด์ ์ํธ๋์ ๊ด๋ฆฌ |
Client Request ํ๋ฉด,
Server์์ HTML์ ๋ด๋ ค์ค ๋ โก๏ธ static
or dynamic
์ผ๋ก ๋ด๋ ค์ค
Controller
Client Request โ Model๋ก ๋ฐ์ ์ฒ๋ฆฌํจ
(ex. ํ์๊ฐ์
์ ์ํ ID, PW, NAME โข โข โข)
Client์๊ฒ View ๋ด๋ ค์ค
(์ ์ ์นํ์ด์ง, HTML)
Controller
Client Request โ Model๋ก ๋ฐ์ ์ฒ๋ฆฌํจ
Templete engine์ View, Model ์ ๋ฌ
Client์๊ฒ View ๋ด๋ ค์ค
(๋์ ์นํ์ด์ง, HTML)
Templete engine
View์ Model์ ์ ์ฉํจ โ ๋์ ์ธ ์นํ์ด์ง ์์ฑ
(ex. ๋ก๊ทธ์ธ ์ฑ๊ณต ์, ๋ก๊ทธ์ธ๋์ฌ์ฉ์Id โ ํ์ด์ง์ ์ถ๊ฐ)
Thymeleaf ์ฌ์ฉ (ํ์๋ฆฌํ)
๐ resources > static > hello.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Hello Mallang</title>
</head>
<body>
<div>
Hello, Mallang ์ ์ ์นํ์ด์ง!!
</div>
</body>
</html>
๐ templates > hello.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Hello Mallang</title>
</head>
<body>
<div>
Hello, Mallang templates ํ์ด์ง!!
</div>
</body>
</html>
๐ templates > hello-visit.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello Mallang</title>
</head>
<body>
<div>
Hello, Mallang ๋์ ์นํ์ด์ง!!
</div>
<div>
(๋ฐฉ๋ฌธ์ ์ : <span th:text = "${visits}"></span>)
</div>
</body>
</html>
๐ controller > HelloResponseController.java
@Controller
@RequestMapping("/response") // ์ ์ฒด url -> /response๋ก ์์
public class HelloResponseController {
// ๋ฐฉ๋ฌธ์์ ์ฆ๊ฐ์ํค๋ ํด๋์ค ๋ณ์
private static long visitCount = 0;
// ์ ์ ์นํ์ด์ง
@GetMapping("/html/redirect")
public String htmlFile() {
return "redirect:/hello.html";
}
// ๋์ ์นํ์ด์ง
@GetMapping("/html/templates")
public String htmlTemplates() {
return "hello";
}
// ์ ์ ์นํ์ด์ง
// ๋ฉ์๋ Return ๊ฐ -> View ์ถ๋ ฅ X
// HTTP Response Body์ ์ฐ์ฌ์ง
// json ๋ฐํ
@ResponseBody
@GetMapping("/body/html")
public String helloStringHTML() {
// return๊ฐ์ด html -> ๋ฐ๋ก ์ ์ฉ๋์ด ๋์ด
return "<!DOCTYPE html>" +
"<html>" +
"<head><meta charset=\"UTF-8\"><title>By @ResponseBody</title></head>" +
"<body> Hello, Mallang ์ ์ ์น ํ์ด์ง!!</body>" +
"</html>";
}
// ๋์ ์นํ์ด์ง
// Thymeleaf๋ฐฉ์
// Model <- Client๊ฐ ์ํ๋ ๊ฐ, hello-visit.html์ ๋ฐํ
@GetMapping("/html/dynamic")
public String helloHtmlFile(Model model) {
visitCount++;
// hello-visit์ visits๋ถ๋ถ์ visitCount ์ฝ์
model.addAttribute("visits", visitCount);
// Controller๋ Model์ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ด, View์ ๋ฐ์ดํฐ๋ฅผ ๋๊น
return "hello-visit";
}
// ๋ฉ์๋ Return ๊ฐ -> View ์ถ๋ ฅ X
// HTTP Response Body์ ์ฐ์ฌ์ง
// json ๋ฐํ
@ResponseBody
@GetMapping("/json/string")
public String helloStringJson() {
// ์ฝ์ <body></body>์ jsonํํ๋ก ์ฐํ
return "{\"name\":\"๋ง๋\",\"age\":20}";
}
@ResponseBody
@GetMapping("/json/class")
public Star helloJson() {
// star ๊ฐ์ฒด๊ฐ json ํํ๋ก ๋ฐํ๋จ
return new Star("๋ง๋", 22);
}
}
๐ entity > Star.java
@Getter
@Setter
// class ๋ชจ๋ ํ๋๊ฐ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๋ ์์ฑ์์ถ๊ฐ
@AllArgsConstructor
public class Star {
public String name;
public int age;
}
๐ @RestController
: @Controller + @ResponseBody
โ View ๋์ , JSON ํํ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ
๐ Controller > HelloRestController.java
// @Controller + @ResponseBody -> Json ํํ์ ๋ฐ์ดํฐ ๋ฐํ
@RestController
@RequestMapping("/rest")
public class HelloRestController {
@GetMapping("/json/string") // ์๋ HTML ๋ฐํ
public String helloHtmlString() {
return "<html><body>Hello @ResponseBody</body></html>";
}
@GetMapping("/json/list") // ๋ฆฌ์คํธ ๋ฐํ
public List<String> helloJson() {
List<String> words = Arrays.asList("Hello", "Controller", "And", "JSON");
return words;
}
}
๋จ๊ณ | ๋์ |
---|---|
1. Client โ DispatcherServlet | - โ Client์ ์์ฒญ์ ๋ฐ์ - โก ๊ฐ์ฅ ์๋จ์์ ์์ฒญ์ ๋ฐ์ โ FrontController ๋ผ๊ณ ๋ ์ฌ์ฉํจ |
2. DispatcherServlet โ Controller | - โ API๋ฅผ ์ฒ๋ฆฌํ Controller๋ฅผ ์ฐพ์ ์์ฒญ์ ์ ๋ฌํจ - โก Handler mapping : API path + Controller ํจ์๊ฐ ๋งค์นญ๋์ด์์ (โ Handler mapping์์ ์๋ง์ Controller ๋งค์นญ์์ผ์ฃผ๋ ์ญํ ) |
3. Controller โ DispatcherServlet | - โ Controller๊ฐ Client๋ก๋ถํฐ ๋ฐ์ API Request ์ฒ๋ฆฌ - โก Model(View์ ์ ์ฉํ ์ ๋ณด๋ค) + View โ DispatcherServlet์ ์ ๋ฌ |
4. DispatcherServlet โ Client | - โ ViewResolver โ View์ Model ์ ์ฉ - โก View โ Client์๊ฒ Response ์ ๋ฌ |
๐ Controller > HelloRequestController
@Controller
@RequestMapping("/request") // request path๋ก ์์
public class HelloRequestController {
// hello-request-form htmlํ์ผ ํธ์ถ
@GetMapping("/form/html")
public String helloForm() {
return "hello-request-form";
}
@GetMapping("/star/{name}/age/{age}")
// View๊ฐ ์๋๋ผ, Jsonํํ์ ๋ฐ์ดํฐ๋ง ๋ฐํ
// @Controller ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ ๋ฉ์๋๋ง๋ค ๋ถ์ฌ์ค์ผํจ
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age) {
// @PathVariable : URL๋ก ์ ๋ฌ๋ ๊ฐ -> ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์ด
return String.format("Hello, @PathVariable. <br> name = %s, age = %d", name, age);
}
// param?name=mallang&age=22 (์ฟผ๋ฆฌ์คํธ๋ง)
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
// @RequestParam : URL๋ก ์ ๋ฌ๋ ๊ฐ -> ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์ด
// Get๋ฐฉ์์ URL์ ๊ฐ์ด ํ์ถ๋จ
return String.format("Hello, @RequestParam. <br> name = %s, age = %d", name, age);
}
@PostMapping("/form/param")
@ResponseBody
public String helloPostRequestParam(@RequestParam String name, @RequestParam int age) {
// Post๋ฐฉ์์ URL์ ๊ฐ์ด ํ์ถ๋์ง ์์
// ํ์ด๋ก๋์ ๊ฐ์ด ๋ค์ด์์
return String.format("Hello, @RequestParam. <br> name = %s, age = %d", name, age);
}
@PostMapping("/form/model")
@ResponseBody
public String helloRequestBodyForm(@ModelAttribute Star star) {
// @ModelAttribute : ํ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒด์ ์ ๋ถ ๋ด์ ๊ฐ์ ธ์ด
return String.format("Hello, @RequestBody. <br> (name = %s, age = %d)", star.name, star.age);
}
@PostMapping("/form/json")
@ResponseBody
public String helloPostRequestJson(@RequestBody Star star) {
// ๊ฐ์ด HTTP Body์ Jsonํํ๋ก ๋์ด๊ฐ
// @RequestBody + ๊ฐ์ ๋ฐ์์ฌ ๊ฐ์ฒด
return String.format("Hello, @RequestBody. <br> (name = %s, age = %d)", star.name, star.age);
}
}
๐ templates > hello-request-form.html
<!DOCTYPE html>
<html lang="ko">
<head>
<title>Hello Request</title>
</head>
<body>
<h2>GET /request/star/{name}/age/{age}</h2>
<form id="helloPathForm">
<div>
์ด๋ฆ: <input name="name" type="text">
</div>
<div>
๋์ด: <input name="age" type="text">
</div>
</form>
<div>
<button id="helloPathFormSend">์ ์ก</button>
</div>
<br>
<h2>GET /request/form/param</h2>
<form method="GET" action="/request/form/param">
<div>
์ด๋ฆ: <input name="name" type="text">
</div>
<div>
๋์ด: <input name="age" type="text">
</div>
<button>์ ์ก</button>
</form>
<br>
<h2>POST /request/form/param</h2>
<form method="POST" action="/request/form/param">
<div>
์ด๋ฆ: <input name="name" type="text">
</div>
<div>
๋์ด: <input name="age" type="text">
</div>
<button>์ ์ก</button>
</form>
<br>
<h2>POST /request/form/model</h2>
<form method="POST" action="/request/form/model">
<div>
์ด๋ฆ: <input name="name" type="text">
</div>
<div>
๋์ด: <input name="age" type="text">
</div>
<button>์ ์ก</button>
</form>
<br>
<h2>POST /request/form/json</h2>
<form id="helloJsonForm">
<div>
์ด๋ฆ: <input name="name" type="text">
</div>
<div>
๋์ด: <input name="age" type="text">
</div>
</form>
<div>
<button id="helloJsonSend">์ ์ก</button>
</div>
<div>
<div id="helloJsonResult"></div>
</div>
</body>
<script>
// GET /star/{name}/age/{age}
const helloPathForm = document.querySelector("#helloPathFormSend")
helloPathForm.onclick = (e) => {
const form = document.querySelector("#helloPathForm");
const name = form.querySelector('input[name="name"]').value;
const age = form.querySelector('input[name="age"]').value;
const relativeUrl = `/request/star/${name}/age/${age}`;
window.location.href = relativeUrl;
}
// POST /hello/request/form/json
const helloJson = document.querySelector("#helloJsonSend")
helloJson.onclick = async (e) => {
const form = document.querySelector("#helloJsonForm");
const data = {
name: form.querySelector('input[name="name"]').value,
age: form.querySelector('input[name="age"]').value
}
const response = await fetch('/request/form/json', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
const text = await response.text(); // read response body as text
document.querySelector("#helloJsonResult").innerHTML = text;
};
</script>
</html>