Spring Boot๋ฅผ ์ฒ์ ๊ณต๋ถํ๋ ์ฌ๋์ด ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํด์ ์์ฑํ ํฌ์คํธ์ ๋๋ค. ์ค๊ฐ๋ ๋ฐ ์ค๋ฅ๊ฐ ์์ ์ ์์ผ๋, ๋ฐ๊ฒฌํ์ ๋ค๋ฉด ๊ฐ๊ฐ์์ด ๋๊ธ์ ํตํด์ ์๋ ค์ฃผ์ธ์! ํ์ธํ๋ ๋๋ก ์ ํํ ์ ๋ณด๋ฅผ ํ์ธํด์ ๊ณ ์น๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ฐ์
์ด๋ฒ Spring Boot ์คํฐ๋๋ ๋ฐฐ๋ฌ์ ๋ฏผ์กฑ์ ๊น์ํ๋๊ป์ ์ธํ๋ฐ์ ์ฌ๋ ค์ฃผ์๋ ์๋ฐ ์คํ๋ง ์์ ์ ๋ณต ์๋ฆฌ์ฆ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์งํํ๋ค. ๊ทธ ์๋ฆฌ์ฆ์ ๊ฐ์ฅ ์ฒซ ๊ฐ์์ธ ์คํ๋ง ์ ๋ฌธ - ์ฝ๋๋ก ๋ฐฐ์ฐ๋ ์คํ๋ง ๋ถํธ, ์น MVC, DB ์ ๊ทผ ๊ธฐ์ ์ ๋ค์ด๋ณด๊ณ ๊ฐ๋จํ ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค.
ํด๋น ๊ฐ์๋ ๋ด๊ฐ ๋๋ผ๊ธฐ์ ํฌ๊ฒ ๋ค์์ ์ปจํ ์ธ ๋ฅผ ๊ฐ์ง๊ณ ์์๋ค.
- Spring ๊ธฐ์ด ๊ธฐ๋ฅ ์จ๋ณด๊ธฐ
- Spring Bean๊ณผ ์์กด ๊ด๊ณ
- ํ์ ๊ด๋ฆฌ ์์ ๊ตฌํํ๊ธฐ
- Controller - Service - Repository ํจํด ์ ์ฉ
- Spring MVC ์ ์ฉ
- ์์ ์์ ์ ๋ค์ํ DB ์ ๊ทผ ๊ธฐ์ ์ ์ฉ
- JDBC
- JDBC Template
- JPA
- Spring Data JPA
- ์์ ์์ ์ ๊ฐ๋จํ AOP ์ ์ฉ
์ด ํฌ์คํธ์์๋ Spring ๊ธฐ์ด ๊ธฐ๋ฅ ์จ๋ณด๊ธฐ์ ๋ํด์ ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ๋ค.
Spring ๊ธฐ์ด ๊ธฐ๋ฅ ์จ๋ณด๊ธฐ
ํด๋น ๊ฐ์๋ Spring Boot์ ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ๊ฐ๋ณ๊ฒ ์ฑ ํ๊ณ ์ง๋๊ฐ๋ ๊ฒ์ ์๋ค ๋ณด๋, ๊ฐ์์ค์ ์์ธํ ์ค๋ช ๋ณด๋ค๋ ๊ฐ๊ด์ ์ธ ์ค๋ช ์ ํตํด์ ๋๋์ ์ธ ๋๋์ ์ ๋ฌํ๋ฉด์ ๊ฐ์๊ฐ ์งํ์ด ๋๋ค.
์ ์ ์ปจํ ์ธ
Spring Boot์์ ์ ์ ์ปจํ
์ธ ๋ฅผ ์๋นํ๊ณ ์ถ์ผ๋ฉด ๋จ์ํ๊ฒ resources/static/
๋๋ ํ ๋ฆฌ์ ์ปจํ
์ธ ๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด Spring์ด ๋ฐ ๋ ์ด๋ฅผ ์๋์ผ๋ก ์ ์ ์ปจํ
์ธ ๋ก ์ธ์ํ์ฌ ์๋นํด์ค๋ค.
์ด์ ์ ๊ทผํ๊ณ ์ถ์ผ๋ฉด ๊ธฐ๋ณธ ์ค์ ์์ผ๋ก๋ ๊ทธ๋ฅ http://<domain>/<static-content-name>
์ ํํ๋ก ์ ๊ทผํ ์ ์๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
MVC์ Template Engine
MVC๋ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ Model๊ณผ ์ฌ์ฉ์์๊ฒ ๋ณด์ด๋ ๋ถ๋ถ์ ๊ด๋ฆฌํ๋ View, ๊ทธ๋ฆฌ๊ณ ์ด ๋ ์ฌ์ด๋ฅผ ์๊ฒ ์ฐ๊ฒฐํ๋ Controller๋ก ๊ตฌ์ฑ๋ ํจํด์ด๋ค. ์ด์ ๋ํ ์ค๋ช ์ ๋ค์์ ๋ค๋ค๋ณด๋ ๊ฒ์ผ๋ก ํ๊ณ , Spring์์๋ ์ด ํจํด์ ์ ๊ทน์ ์ผ๋ก ํ์ฉํ๋ Spring MVC๋ผ๋ ๊ฒ์ด ์๋ ๊ฒ์ผ๋ก ์๊ณ ์๋ค.
์ผ๋จ ์ด MVC์ ์์๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๊ฐ์์์์ Template Engine์ธ ThymeLeaf๋ฅผ ์ฌ์ฉํ๋ค. Template Engine์ html์ ๋์ ์ผ๋ก ์์ฑํด์ฃผ๊ธฐ ์ํ ์์ง์ผ๋ก ์ด๋ ํ Template์๋ค ์ธ๋ถ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ฃผ์ด ๊ทธ๊ฒ์ ํตํด์ ๋์ ์ผ๋ก html์ ์์ฑํ๊ฒ ๋๋ค.
๊ทธ๋ฆฌ๊ณ Controller๋ฅผ ์์ฑํด์ฃผ๊ฒ ๋๋๋ฐ, Spring Boot ํ๋ก์ ํธ์์ SpringBootApplication
์ด ์๋ ํจํค์ง ์์ controller
๋ผ๋ ํจํค์ง๋ฅผ ์์ฑํ๊ณ , ๊ทธ ์์ <name>Controller
์ ํํ๋ก Controller ํด๋์ค๋ฅผ ์์ฑํ๋ค. ๊ฐ์์์๋ HelloController
๋ผ๋ ์ด๋ฆ์ผ๋ก ์์ฑํ์๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.
@Controller
public class HelloController {
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "hello-template";
}
}
Spring ๊ณต๋ถ๋ฅผ ํ๋ค ๋ณด๋ฉด ๋ง์น ๋ง๋ฒ๊ณผ ๊ฐ์ด ๋๊ปด์ง๋ ๊ฒ๋ค์ด ๋ง์ด ์๋๋ฐ, ๊ทธ ์ค ํ๋๊ฐ ๋ฐ๋ก ์์ ์ฝ๋์์ ์ฌ์ฉํ ์ด๋
ธํ
์ด์
(Annotation)๋ค์ด๋ค. @<annotation-name>
๋๋ @<annotation-name>(...args)
์ ํํ๋ก ์ฌ์ฉํ๋๋ฐ, ์ด๊ฒ๋ค์ด ์๋์ ๊ตฌํ๋ ํด๋์ค์ ํน์ ๊ธฐ๋ฅ์ด๋ ๋์ ๋ฑ์ ๋ถ์ฌํด์ ํน์ ๋ชฉ์ ์ ๋ถํฉํ๊ฒ ๋์ํ๋๋ก ๋ง๋ค์ด ์ค๋ค.
์์ ์ฝ๋์ ๊ฒฝ์ฐ @Controller
์ @GetMapping("hello-mvc")
๊ทธ๋ฆฌ๊ณ @RequestParam("name")
๊ฐ ์ฌ์ฉ๋์๋๋ฐ, @Controller
๋ ๊ทธ์ public class์ธ HelloController
๋ฅผ Spring ์์์ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋ Controller๋ก ๋ง๋ค์ด์ฃผ๊ณ ,
@GetMapping("hello-mvc")
๋ HTTP GET ์์ฒญ์ด /hello-mvc
๋ก ๋ค์ด์ฌ ๊ฒฝ์ฐ ์๋์ ํจ์๊ฐ ์คํ๋ ์ ์๋๋ก Mapping ํด์ค๋ค. ์ฌ์ง์ด, @RequestParam("name")
๋ URL Parameter์์ name์ ์์์ ๋ฝ์๋ด์ ๊ทธ๊ฒ์ ํจ์ ํ๋ผ๋ฏธํฐ name์ ๋ฃ์ด์ค๋ค. ์ด๋ฐ ๊ฒ๋ค์ ์ฐ๋ฆฌ๊ฐ ์ง์ ๊ตฌํํ๋ ๊ฒ์ด ์๋๋ผ ๊ทธ๋ฅ ์ ์ ํ ์ด๋
ธํ
์ด์
์ ๊ฐ์ ธ๋ค ์ฐ๋ฉด ์ต๊ฐํด์๋ ์ต์ ํ๋ ํํ๋ก ๋ง๋ฒ๊ฐ์ด ๊ตฌํ๋๋ ๊ฒ์ด Spring์ ๊ฐ์ ์ด์ง ์๋ ์ถ์๋ค.
์ด์จ๋ , Controller์ ํน์ Mapping๋ ๋ฉ์๋์์๋ String ํํ์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ฐํํ๋๋ฐ, ์ด๊ฒ์ ๋ฐ๋ก ์ฐ๋ฆฌ๊ฐ ๋ง๋ค๊ณ ์ ํ๋ Template์ ํ์ผ ์ด๋ฆ, ์ฆ View์ ํ์ผ ์ด๋ฆ์ด๋ค. ์ ๊ฑธ String ํํ๋ก ๋ฐํํด์ฃผ๋ฉด (๋ฌผ๋ก ๊ต์ฅํ ๋ณต์กํ ์ธ๋ถ์ ๊ตฌํ์ด ์๊ฒ ์ง๋ง ์ง๊ธ ๋จ๊ณ์์๋) Spring์ด ์์์(ใ ใ ) ํด๋น Template์ ๋ถ๋ฌ์์ ์ ์ ํ Template Engine์ ์คํํด HTML์ ์์ฑํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ฐํํ๊ฒ ๋๋ค.
์, ์ Controller ๋ฉ์๋ ์์ model์ด ๋ญ๋๊ณ ? ์ ํํ๊ฒ ๊ฐ์์ ๋์ค์ง๋ ์์ง๋ง ThymeLeaf์์ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ์ธ ๋ฏ ํ๋ค. ์์ ์ฝ๋์์๋ name
์ด๋ผ๋ attribute๋ฅผ model์ ๋ฃ์ด์ฃผ์๋๋ฐ, ์ด๋ฅผ Template ์์์ ๋ค์๊ณผ ๊ฐ์ด ํ์ฉํ๋ค.
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
์ฌ๊ธฐ์ html attribute๋ก th:
๋ผ๊ณ ๋์ด์๋ ๊ฒ๋ค์ด ์๋๋ฐ, ์ด๋
์๋ค์ด ๋ฐ๋ก ThymeLeaf Template Engine์ ์ฌ์ฉํ๋ ๋
์๋ค์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฑฐ๊ธฐ ๋ณด๋ฉด ${name}
์ผ๋ก name์ด๋ผ๋ ๋
์์ ๊ฐ์ ธ๋ค ์ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๊ทธ๋ ๋ค, ์ด name
์ด ์์ Controller์์ model์ attribute๋ก ์ถ๊ฐํด์ค ๊ทธ ๋
์์ด๋ค.
API
์ต๊ทผ์๋ Spring MVC ์ฒ๋ผ ์๋ฒ์์ html์ ์์ ํ ์์ฑํด์ ๋๋ ค์ฃผ๋ SSR ๋ฐฉ์ ์ด์ธ์๋ React๋ Vue์ฒ๋ผ ํด๋ผ์ด์ธํธ ์์์ ์๋ฒ๋ก๋ถํฐ๋ ๋ฐ์ดํฐ๋ง ์ ๋ฌ๋ฐ์ ๋ ๋๋งํ๋ CSR ๋ฐฉ์, ํน์ ์ด ๋์ ์ ์ ํ ์์ด์ ์ฌ์ฉํ๋ ๋ฐฉ์๋ค๋ ๋ง์ด ์ฐ์ด๊ณ ์๋ค.
์๋ฐํ๊ฒ ๋งํ์๋ฉด API๋ ์ด๋ณด๋ค ๋ ๋ง์ ์๋ฏธ๋ฅผ ๊ฐ์ง๊ณ ์์ง๋ง, ์ฝ๊ฒ ์๊ฐํด์ API ์๋ฒ๋ฅผ ๋ง๋ ๋ค๊ณ ํ๋ฉด ์ ๋ฐ ๊ณณ์ ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ฐํํด์ฃผ๋ ์๋ฒ๋ฅผ ๋ง๋๋ ๊ฒ์ด๋ค.
Spring์์๋ ๋น์ฐํ API ์๋ฒ๋ฅผ ๊ฐ๋จํ๊ฒ ๋ง๋ค ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค. Controller์ ๋ฉ์๋๋ฅผ ์์ฑํ ๋ @ResponseBody
๋ผ๋ ์ด๋
ธํ
์ด์
ํ๋๋ง ๋ถ์ฌ์ฃผ๋ฉด ๋์ด๋ค.
@Controller
public class HelloController {
@GetMapping("hello-string")
@ResponseBody
public String helloString(@RequestParam("name") String name) {
return "hello " + name;
}
}
๊ทธ๋ฌ๋ฉด Spring์์ ๋ฌธ์์ด์ ๋ฐํํ๋๋ผ๋, ๊ทธ ๋ฌธ์์ด์ ํด๋นํ๋ View๋ฅผ ์ฐพ์ผ๋ ค๊ณ ํ์ง ์๊ณ ์ ๋ฌธ์์ด ์์ฒด๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ฐํํ๊ฒ ๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ณดํต API ์๋ฒ์ ์์ฒญ์ ๋ณด๋ผ ๊ฒฝ์ฐ ๋๊ฐ JSON ํํ๋ก ์๋ต์ ๋ฐ๊ฒ ๋๋ค. ์ ์ฒ๋ผ ๊ทธ๋ฅ ๋ฌธ์๊ฐ ์๋๋ผ JSON์ ๋ฐํํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
@Controller
public class HelloController {
@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;
}
}
}
๊ฐ๋จํ๋ค. ๊ทธ๋ฅ ๊ฐ์ฒด ๋ง๋ค์ด์ ์ธ์คํด์ค ํ๋ ์์ฑํ๊ณ , ๊ทธ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ทธ ๊ฐ์ฒด๋ฅผ Spring์์ JSON ํํ๋ก ์ง๋ ฌํ(Marshalling)ํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ฐํํด์ค๋ค. Go ์ธ์ด์์ ๋ฐ์ดํฐ๋ฅผ JSON ํํ๋ก ๋ง๋ค๋ ค๊ณ ๋๋ฆฌ๋ฅผ ์ณค๋ ๊ฒฝํ์ด ๋๋ฌด๋๋ ํ๋ฌดํด์ง๋ ์๊ฐ์ด์๋ค.
๋ค์์
๋ค์ ํฌ์คํธ์์๋ Spring Bean๊ณผ ์์กด ๊ด๊ณ์ ๋ํ ๊ฐ์ ๋ด์ฉ์ ๊ฐ๋ตํ ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ๋ค.
๋.