๐ฆซSection 1. ํ๋ก์ ํธ ํ๊ฒฝ์ค์
ํ๋ก์ ํธ ์์ฑ
์ค๋นํด์ผํ ๊ฒ.
Java 11 ์ค์น→ ๋ฒ์ ์ด์ ๋๋ฌธ์ Java 17- IDE (InteliJ) ์ค์น
(์๋ ์๋ Spring ํ๋ก์ ํธ๋ฅผ ๋ฐ๋ฐ๋ฅ ๋ถํฐ ๋ง๋ค์์ง๋ง ์์ฆ์ Spring-boot ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Spring ํ๋ก์ ํธ๋ฅผ ๋ง๋ฌ!!)
Spring-boot ๊ธฐ๋ฐ์ผ๋ก Spring ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด์ฃผ๋ ์ฌ์ดํธ์ด๋ค (Spring ์์ ์ด์์ค์!!)
๊ณผ๊ฑฐ์๋ Maven์ ์ฃผ๋ก ์ฌ์ฉํ์ง๋ง ์์๋ ๊ฑฐ์๋ค Gradle ์ ์ฌ์ฉํ๋ค๊ณ ํ๋ค…
SNAPSHOT์ ์์ง ์ถ์ ์ ์ด๋ฏ๋ก SNAPSHOT ์ด ์๋๊ฒ๋ค์ค ์ ์ผ ๋์ ๋ฒ์ ์ ์ ํ!
Group์ ํ์ฌ ์ด๋ฆ์ ์์ฑํ๋ ๊ณณ์ธ๋ฐ ๋ํ์์ธ ๊ด๊ณ๋ก hello ๋ก ์ฑ์ด๋ค!
Artifact ๋ ํ๋ก๊ทธ๋จ๋ช ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค!! (๋น๋ํ์ ๋ ๋์ค๋ ๊ฒฐ๊ณผ๋ฌผ~?)
Dependencies ๋ ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ก๊ฒจ์ ์ธ ๊ฒ์ธ๊ฐ๋ฅผ ์ค์ !
→ Web ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๊ฒ์ด๋ฏ๋ก Spring Web ๋ฅผ ์ฌ์ฉ
→ HTML ์ ๋ง๋ค์ด์ฃผ๋ ํ ํ๋ฆฟ ์์ง์ธ Thymleaf ๋ฅผ ์ฌ์ฉ
GENERATE ๋ก ๋ค์ด๋ฐ์์ฃผ๊ณ InteliJ ์์ bulid.gradle ์ ์ด์ด์ค๋ค!!
๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๋ฉด .idea ๋ inteliJ ๊ฐ ์ฌ์ฉํ๋ ์ค์ ํ์ผ์ด๊ณ , gradle ์ gradle ๊ณผ ๊ด๋ จํด์ gradle์ ์ฌ์ฉํ๋ ํด๋์ด๊ณ
src ์์ main ๊ณผ test ํด๋๊ฐ ๋๋ ์ ธ ์์ด์ main ์๋ java ์ ๊ทธ ๋ฐ์ ์ค์ ์์คํ์ผ๋ค์ด ์๊ณ test ์์๋ test ์ฝ๋๋ค๊ณผ ๊ด๋ จ๋ ์์ค๋ค์ด ๋ค์ด์๋ค!! (์์ฆ ๊ฐ๋ฐ ํธ๋ ๋์์๋ test๊ฐ ์ค์ํ๋ค!)
resources ์์๋ ์ค์ java ์ฝ๋ ํ์ผ๋ค์ ์ ์ธํ xml ์ด๋ html, ์ค์ ํ์ผ ๋ฑ์ด ๋ค์ด์์!
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
}
// java ์ธ์ด๋ฅผ ์ ํํ๋ ๊ฒ๋ค๊ณผ ๊ด๋ จ๋ ๋ด์ฉ์ด plugins ์ ๋ค์ด๊ฐ ์์
group = 'hello'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
์ ๋ฌธ ๋จ๊ณ์์๋ gradle ์ด ๋ฒ์ ์ ์ค์ ํ๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๋๊ตฌ๋!! ๋ง ์ดํดํ๊ณ ๋์ด๊ฐ๋ฉด ๋จ
dependencies ๋ ์๊น ๋ค์ด๋ฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์!!
→ repositories ์ ์๋ mavenCentral ๋ผ๋ ๊ณต๊ฐ๋ ์ฌ์ดํธ์์ ๋ค์ด๋ฐ์ผ๋ผ๊ณ ์ค์ ํด๋์ ๊ฒ์! (์๊ธฐ๊ฐ ์ํ๋ ํน์ ์ฌ์ดํธ๋ฅผ ๋ฃ์ด๋ ๋จ)
package hello.hellospring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloSpringApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringApplication.class, args);
}
}
๐ก ๊ฐ์์์๋ JAVA 11์ ์ฌ์ฉํ์ง๋ง ๋ฒ์ ์ด์ ๋๋ฌธ์ ์คํ์ด ์ ๋๋ ๊ด๊ณ๋ก 17๋ก ๋ค์ด๋ก๋ํด์ ์งํํ์ต๋๋ค…
main ํจ์๋ฅผ ์คํ์ํค๋ฉด ์ด๋ ๊ฒ ์ซ ๋จ๋๊ฑธ ํ์ธํ ์ ์์ต๋๋ค~
์คํ๋๋ ์๋ฆฌ๋ main ๋ฉ์๋๋ฅผ ์คํํ๋ฉด SpringApplication.run ์ ํตํด SpringBootApplication ์ด ์คํ๋๋ฉด์ Tomcat ์ด๋ผ๋ ์น์๋ฒ๋ฅผ ๋ด์ฅํ๊ณ ์๋๋ฐ ๊ทธ๊ฒ์ ์์ฒด์ ์ผ๋ก ๋์ฐ๋ฉด์ SpringBoot๋ ๊ฐ์ด ์ฌ๋ผ์จ๋ ๋จธ์๊ธฐ ๊ทธ๋ฐ..
์ค์ ์์ Gradle ์ ๊ฒ์ํ ํ ๋ค์๊ณผ ๊ฐ์ด InteliJ ๋ก ๋ฐ๊ฟ์ฃผ๊ฒ ๋๋ฉด Gradle ์ ํตํด run์ด ์คํ๋์ง ์๊ณ ๋ฐ๋ก InteliJ ์์ JAVA๋ฅผ ์คํํ๋ฏ๋ก ํจ์ฌ ๋น ๋ฆ! (๊ฟํ)
์ฌ๋ฌ ๋ด์ฉ๋ค์ค์์ Tomcat started on port(s): 8080 (http) with context path '’ ๊ฐ ์ค์ํ๋ฐ
localhost:8080 ์ ์ ์ํ๋ฉด ์๋์ ๊ฐ์ ํ๋ฉด์ด ๋จ๋ฉด ํ๋ก์ ํธ ํ๊ฒฝ์ค์ ์ด ์ฑ๊ณต์ ์ผ๋ก ๋ ๊ฒ์ ๋๋ค!!
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ดํด๋ณด๊ธฐ
Gradle์ ์์กด(์ฐ๊ด) ๊ด๊ณ๊ฐ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํจ๊ป ๋ค์ด๋ก๋ ํ๋ค!
์คํ๋ง ๋ถํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- spring-boot-starter-web
- spring-boot-starter-tomcat : ํฐ์บฃ (์น์๋ฒ)
- spring-webmvc : ์คํ๋ง ์น MVC
- spring-boot-starter-thymeleaf : ํ์๋ฆฌํ ํ ํ๋ฆฟ ์์ง(View)
- spring-boot-starter(๊ณตํต) : ์คํ๋ง ๋ถํธ + ์คํ๋ง ์ฝ์ด + ๋ก๊น
- spring-boot
- spring-core
- spring-boot-starter-logging
- (์ค๋ฌด์์๋ System.out.println ์ ์์ฐ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํ ์ค์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ค์ ์ถ์ ํ๊ณ , ๋ฌธ์ ํด๊ฒฐ๊ณผ ์ฑ๋ฅ ๋ถ์์ ๋์์ ์ฃผ๋ logging ์ ์ด๋ค๊ณ ํ๋ค์..)
- logback, slf4j (์์ ์ถ์๋ ์ด 2๊ฐ์ง ์กฐํฉ์ผ๋ก logging ์ ํจ)
- (์ค๋ฌด์์๋ System.out.println ์ ์์ฐ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํ ์ค์ ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ค์ ์ถ์ ํ๊ณ , ๋ฌธ์ ํด๊ฒฐ๊ณผ ์ฑ๋ฅ ๋ถ์์ ๋์์ ์ฃผ๋ logging ์ ์ด๋ค๊ณ ํ๋ค์..)
- spring-boot
ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- spring-boot-starter-test
- junit : ํ ์คํธ ํ๋ ์์ํฌ
- mockito : ๋ชฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- assertj : ํ ์คํธ ์ฝ๋๋ฅผ ์ข ๋ ํธํ๊ฒ ์์ฑํ๊ฒ ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- spring-test : ์คํ๋ง ํตํฉ ํ ์คํธ ์ง์
Gradle ์ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐ๊ด ๊ด๊ณ๋ฅผ ๋ฐ์ ธ์ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค ๋ถ๋ฌ์ค๊ธฐ ๋๋ฌธ์ ์ค์ ์ฐ๋ฆฌ๊ฐ ์ ํํ starter-web ๊ณผ starter-thymeleaf ์ธ์๋ ์ฌ๋ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค!!
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ์๋ ๊ทธ๋ฅ ํ๋ฒ ์ญ ๋ณด์๋ ๊ฑฐ ์ถ์ฒ๋๋ ค์…
(์ด๋ฐ ๊ฒ ์๊ตฌ๋๋ง ์๊ณ ๋์ด๊ฐ๋ฉด ๋๋ต๋๋ค!!)
View ํ๊ฒฝ์ค์
์๊น localhost:8080 ์ ๋ค์ด๊ฐ์ ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค! (๋น์ฐํ ์๋ฌด๊ฒ๋ ์ํ์ผ๋๊น…)
๊ทธ๋์ ์ด๋ฒ์๋ Welcom Page ๋ฅผ ๋ง๋ค๊ฑด๋ฐ src / main / resources / static ์ index.html ์ ๋ง๋ค๋ฉด ๊ทธ๊ฒ์ Welcom page ๋ก ํด์ค (๋๋ฉ์ธ์ ๋๋ฅด๊ณ ์์ ๋ ์ฒซ ํ๋ฉด)
<!DOCTYPE HTML>
<html>
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content = "text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href = "/hello">hello</a>
</body>
</html>
์๋ ๊ฒ ๋ง๋ค์ด ์ฃผ์ ๋ค์์ ์๋ฒ๋ฅผ ํค๊ณ localhost:8080 ์ ์ ์ํด๋ณด๋ฉด
์ด๋ ๊ฒ ์ ๋์ค๋ ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค~
๐กWelcom page ๋ ์ด๋ป๊ฒ ๋ง๋ค์ง..? ๋ผ๋ ์๊ฐ์ด ๋๋๋ฐ ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด?!
-> Srping.io ์ ๋ค์ด๊ฐ์!! projects → Spring Boot ์ ๋ค์ด๊ฐ ํ ๋ฉ๋ด์ผ์์ ์ด์ฌํ ์ฐพ์๋ณธ๋ค… (Spring Boot ๊ฐ ์ ๊ณตํด์ค!!)
์คํ๋ง ๋ถํธ๊ฐ ์ ๊ณตํ๋ Welcom Page ๊ธฐ๋ฅ์ ๊ทธ์ ํ์ผ๋ง ๋๊ฒจ์ฃผ๋ ์ ์ ํ์ด์ง์ ๋๋ ์ด์ง๋ง!!
thymeleaf (์ฒ์์ ๊ฐ์ ธ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ!!) ์ ๊ฐ์ ํ ํ๋ฆฟ ์์ง์ ์ฌ์ฉํ๋ฉด ํ์ด์ง๋ฅผ ๋ณ๊ฒฝํ ์ ์์!!
-> ์คํ๋ง ๋ถํธ ๋ฉ๋ด์ผ, thymeleaf ๊ณต์ ์ฌ์ดํธ ๋ฑ์์ ์ฐพ์๋ณด์ธ์~
์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฒซ๋ฒ์งธ ์ง์ ์ ์ด ์ปจํธ๋กค๋ฌ(controller) ์ด๋ค!!
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"> <!-- ์ด ์ค์ ๋ฃ์ด์ค์ผ thymeleaf ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์๋ค. -->
<head>
<title>Hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'์๋
ํ์ธ์. ' + ${data}" >์๋
ํ์ธ์. ์๋</p> <!-- th ๋ thymeleaf ์ด๋ค! -->
<!-- data ๋ ์๊น controller ์ model.addAttribute ์์ ๋๊ฒจ์ค hello!! ์ ๊ฐ์ผ๋ก ์นํ๋๋ค. -->
</body>
</html>
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller //controller ์ด๋
ธํ
์ด์
์ ์ ์ด์ค์ผ ํ๋ค.
public class HelloController {
@GetMapping("hello") // Map ์ดํ๋ฆฌ์ผ์ด์
์์ /hello ๊ฐ ๋ค์ด์ค๋ฉด ์ด ๋ฉ์๋๋ฅผ ํธ์ถํด์ค๋ค (Spring ์ด ํด์ค)
public String hello(Model model) {
model.addAttribute("data", "hello!!");
return "hello";
}
}
์ ์ด๋ ๊ฒ ํ์ผ 2๊ฐ ๋ง๋ค์ด์ค ๋ค์์! ์๋ฒ๋ฅผ ํค๊ณ localhost::8080/hello ์ ๋ค์ด๊ฐ๋ณด๋ฉด!!
์ด๋ ๊ฒ ์ ๋จ๋๊ฑธ ํ์ธํด๋ณผ ์ ์์ต๋๋ค~
๊ทธ๋ฌ๋ฉด ์ด์ฏค์์ ์๋ ์ด๊ฒ ์ด๋ป๊ฒ ์๋์ด ๋๋๊ฑฐ์ง..? ํ๋ ๊ถ๊ธ์ฆ์ด ์๊ธฐ๋๋ฐ
์ฝ๊ฒ ํ์ด๋ณด์๋ฉด!!
์น ๋ธ๋ผ์ฐ์ ์์ (์ฌ๊ธฐ์๋ localhost:8080/hello) /hello ๋ฅผ ๋์ง๋ฉด ์คํ๋ง ๋ถํธ๋ ๋ด์ฅ๋ ํฐ์ผ ์น์๋ฒ์์ ์ด๊ฑธ ๋ฐ์์ Spring ์๊ฒ ๋ฌผ์ด๋ด
-> ๊ทธ๋ฌ๋ฉด Spring ์ controller (์ฌ๊ธฐ์๋ HelloController) ์์ GetMapping(”hello”) ์ “hello” ์ url์ด ๋งค์นญ๋์ด ๋ฉ์๋๊ฐ ์คํ๋๊ณ Spring ์ด model (key๋ data ์ด๊ณ value ๋ hello!!) ์ด๋ผ๋ ๊ฒ์ ๋ง๋ค์ด์ ๋ฃ์ด์ฃผ๊ฒ ๋๋ค ์ด ๋ return ์ hello ์ด๋ค!!
(return ์ด hello ์ธ ๊ฒ์ templates/hello.html ์ ํ์ผ ์ด๋ฆ๊ณผ ๋์ผํ๋ฐ ์ด๊ฒ์ ์ฐ์ฐ์ด ์๋๋ผ Thymleaf ํ ํ๋ฆฟ ์์ง ์ฒ๋ฆฌ๋ฅผ ์ํด hello.html ์ ์ฐพ์์ model(data ๊ฐ hello! ์ธ) ์ ๋๊ฒจ์ฃผ๊ณ ํ๋ฉด์ ์คํ์ํค๋ผ๋ ์๋ฏธ์ด๋ค!)
Controller ์์ return ๊ฐ์ผ๋ก ๋ฌธ์๋ฅผ ๋ฐํํ๋ฉด ๋ทฐ ๋ฆฌ์กธ๋ฒ(viewResolver) ๊ฐ ํ๋ฉด์ ์ฐพ์์ ์ฒ๋ฆฌํ๋ค.
→ ์คํ๋ง ๋ถํธ ํ ํ๋ฆฟ ์์ง์ ๊ธฐ๋ณธ์ ์ผ๋ก viewName ์ ๋งคํํ์ฌ resources/templates/ + ViewName.html ์ ๊ฐ์ด ๋์ํ๋ฏ๋ก hello ๋ฅผ return ํ๋ฉด hello.html ํ์ผ์ ์ฐพ์์ ํ๋ฉด์ ๊ทธ๋ ค์ค๋ค!!
๐ก spring-boot-devtools ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ฉด ‘html’ ํ์ผ์ ์ปดํ์ผ๋ง ํด์ฃผ๋ฉด ์๋ฒ ์ฌ์์ ์์ด View ํ์ผ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
InteliJ ์ปดํ์ผ ๋ฐฉ๋ฒ : build → Recompile
๋น๋ํ๊ณ ์คํํ๊ธฐ
๋น๋๋ฅผ ํด์ ์ค์ ์คํํ ์ ์๋ ํ์ผ์ ๋ง๋ค์ด๋ณด์!
ํฐ๋ฏธ๋์
- ./gradlew build
- cd build/libs
- java -jar hello-spring-0.0.1-SNAPSHOT.jar
- ์คํํ์ธ
์์๋ก ์งํ!!
→ ๋์ค์ jar ํ์ผ ํ๋๋ง ๋ฃ์ด๋๊ณ ์คํ์ํค๋ฉด ๋๋จ.. (์์ ๊ฐ๋จ)
๐ฆซSection 2. ์คํ๋ง ์น ๊ฐ๋ฐ ๊ธฐ์ด
์น์ ๊ฐ๋ฐํ๋๋ฐ๋ ํฌ๊ฒ 3๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค!!
์ ์ ์ปจํ ์ธ
Welcom Page ์ฒ๋ผ ๊ทธ๋ฅ ์๋ฒ์์ ํ๋๊ฑฐ ์์ด ํ์ผ์ ์น ๋ธ๋ผ์ฐ์ ์ ๊ทธ๋๋ก ๋ด๋ ค์ฃผ๋ ๊ฒ์ด๋ค.
์คํ๋ง ๋ถํธ๋ ์ ์ ์ปจํ ์ธ ๊ธฐ๋ฅ์ ์๋์ผ๋ก ์ ๊ณตํ๋ค.
→ resources/static ์ ํ์ผ์ ๋ง๋ค๋ฉด ๋จ
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
์ ์ ์ปจํ
์ธ ์
๋๋ค.
</body>
</html>
url ์ ํ์ผ๋ช ๊ทธ๋๋ก ๋ค์ด์ค๋ฉด ๋๋ค.
์ด์งธ์ ์ด๋ ๊ฒ ๋ ๊น..? ๋ผ๋ ์๊ฐ์ด ๋คํ ๋ฐ
์น ๋ธ๋ผ์ฐ์ ์์ localhost:8080/hello-static.html ์ ์น๊ฒ๋๋ฉด ๋ด์ฅ ํฐ์ผ ์๋ฒ๊ฐ ์ด ์์ฒญ์ ๋ฐ๊ณ ์คํ๋ง์๊ฒ ๋๊ฒจ์ค!
๊ทธ๋ฌ๋ฉด controller (์ปจํธ๋กค๋ฌ๊ฐ ์ฐ์ ์์๋ฅผ ๊ฐ์ง) ์์ ๋จผ์ hello-static.html ์ด ์๋ ํ์ธํด๋ด (๋งคํ ๋๊ฒ ์์!)
→ resources / static ์์ hello-static.html ์ ์ฐพ์๋ด
์ด๋ ๊ฒ ํด์ ๋ง์ฝ ์ฐพ๊ฒ ๋๋ค๋ฉด hello-static.html ์ ๋ฐํํด์ฃผ๋ ์๋ฆฌ์!
MVC์ ํ ํ๋ฆฟ ์์ง
๊ฐ์ฅ ๋ง์ด ํ๋ ๋ฐฉ์์ด๋ค!!
ํ ํ๋ฆฟ ์์ง์ผ๋ก ์๋ฒ์์ ํ๋ก๊ทธ๋๋ฐ ํด์ html์ ๋์ ์ผ๋ก ๋ฐ๊ฟ์ ๋ด๋ ค์ฃผ๋ ๊ฒ์ด๋ค.
(ํ ํ๋ฆฟ ์์ง์ MVC = model, view, controller ๋ก ์ชผ๊ฐ์ ์ฌ์ฉํ๋ค.)
์ ์ ์ปจํ ์ธ ์ ๋ค๋ฅด๊ฒ ์๋ฒ์์ ๋ณํ์ ํ๋ค!!
์๋ ์๋ View์์ ๋ชจ๋ ๊ฑธ ๋คํ์ง๋ง ์์๋ MVC ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
(View ๋ ์ค์ง ํ๋ฉด์ ๊ด๋ฆฌํ๋ ์ผ๋ง!! ์๋ฒ ๊ด๋ จ์ controller ์์ ์ฒ๋ฆฌํ๊ณ model ์ ํ๋ฉด์ ํ์ํ ๊ฒ ๋ค์ ๋ด์์ ๋๊ฒจ์ฃผ๋ ๋๋)
*Controller*
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model) {
//RequestParam ์ ํตํด ์ธ๋ถ์์ url parameter ๋ก ๋ฐ๋๋ค.
model.addAttribute("name", name);
//parameter ๋ฅผ ๋ฐ์์ name ์ผ๋ก model์ ๋ด๊ฒจ์ ธ์ temmplate๋ก ๋์ด๊ฐ
return "hello-template";
}
*View*
<html xmlns:th="http://www.thymeleaf.org"> <!--thymeleaf ํ
ํ๋ฆฟ ์์ง์ ์ฌ์ฉํด์ผํจ -->
<body>
<p th:text="'hello ' + ${name}">hello! empty</p> <!-- -->
</body>
</html>
๐ก thymeleaf ์ ์ฅ์ ์ ๊ฒฝ๋ก๋ฅผ ๋ณต์ฌํด์ ์๋ฒ ์์ด html๋ง ์ด์ด์ ๊ป๋ฐ๊ธฐ (์์ค) ๋ฅผ ํ์ธ ํ ์ ์๋ค!
→ hello-template.html ์์ p ํ๊ทธ์ ์๋ hello! empty ๋ ์๋ฒ ์์ด html๋ง ๋ณผ ๋ ํ์ธํ๋ ค๊ณ ํ๋ ๊ฒ์ด๊ณ ์ค์ ์๋ฒ๋ฅผ ํ์ ๋๋ฉด th:text="'hello ' + ${name}" ๋ก ๊ฐ์ด ๋ฐ๋๊ฒ ๋๋ค!!
๊ทธ๋ ๊ฒ ํด์ ์๋ฒ๋ฅผ ํค๊ณ localhost:8080/hello-mvc ๋ฅผ ํด๋ณด๋ฉด…
์ ์ค๋ฅ๊ฐ??!
์๋์ฐ ๊ธฐ์ค ctrl + p ๋ฅผ ๋๋ฌ๋ณด๋ฉด required ๊ฐ true๋ก default ๋์ด ์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒ์ ์ ์ ์๋ค. (์๋ฌด๊ฒ๋ ์๋๊ฒผ์ผ๋๊น!!)
http get ๋ฐฉ์์ผ๋ก ? ๋ค์ parameter ๋ฅผ ๋๊ฒจ์ฃผ๋ฉด
์์ฃผ ์ ๋์ค์ฃ ??
์๋ฆฌ๋ฅผ ์์๋ณด์๋ฉด!!
์น ๋ธ๋ผ์ฐ์ ์์ localhost:8080/hello-mvc ๋ฅผ ๋๊ธฐ๋ฉด ์คํ๋ง๋ถํธ๊ฐ ๋ด์ฅ ํฐ์ผ ์๋ฒ ๋์ฐ๊ณ ์คํ๋งํํ ๋์ง๊ณ !
๊ทธ๋ฌ๋ฉด ์๊น ๋งํ๋ฏ์ด Controller ๋ถํฐ ์ฐ์ ์์๊ฐ ์๊ธฐ์ ํ์ธ์ ํด๋ณด๋๋ฐ..!!
hello-mvc ๋ฉ์๋์ ๋งคํ์ด ๋์ด์์ผ๋๊น ํธ์ถํ๊ณ return ์ hello-template ๋ก ์คํ๋ง์๊ฒ ๋๊ฒจ์ค๋ค
→ ๊ทธ๋ ๊ฒ ๋๋ฉด viewResolver (view ๋ฅผ ์ฐพ์์ฃผ๊ณ ํ ํ๋ฆฟ ์์ง์ ์ฐ๊ฒฐ์์ผ์ค) ๊ฐ return ๊ฐ๊ณผ ์ด๋ฆ์ด ๊ฐ์ templates/hello-template.html ์ ์ฐพ์์ HTML ์ ๋ณํํ ํ์ ์น ๋ธ๋ผ์ฐ์ ์ ๋ฐํํจ!!
API
json ์ด๋ผ๋ ๋ฐ์ดํฐ ํฌ๋งท์ผ๋ก client ์๊ฒ ์ ๋ฌํ๋ ๊ฒ์ API ๋ฐฉ์์ด๋ผ๊ณ ํ๋ค!
@GetMapping("hello-string")
@ResponseBody //http ์์ header ๋ถ๋ถ๊ณผ body ๋ถ๋ถ์ด ์๋๋ฐ body ๋ถ๋ถ์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ฃผ๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
public String helloString(@RequestParam("name") String name) {
return "hello " + name; //name ์ spring ์ ๋ฃ๋๋ค๋ฉด "hello spring" ์ด ๋๋๋ฐ ์ด๊ฒ ์์ฒญํ ํด๋ผ์ด์ธํธ์๊ฒ ๊ทธ๋๋ก ๋ด๋ ค๊ฐ
}
์๋ฒ๋ฅผ ํจ ํ์ ํ์ด์ง ์์ค ๋ณด๊ธฐ๋ฅผ ๋๋ฌ๋ณด๋ฉด!!
html ์ด ํ๋๋ ์์ด ๋ฌธ์๋ง ์๋๊ฑธ ํ์ธํ ์ ์๋ค.
(ํ ํ๋ฆฟ ์์ง์ ํ๋ฉด์ ๊ฐ์ง๊ณ view ๋ผ๋ ํ ํ๋ฆฟ์ผ๋ก ์กฐ์ํ๋ ๋ฐฉ์์ด์ง๋ง @ResponseBody ๋ฅผ ์ฌ์ฉํ๋ฉด viewResolver ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ HTTP ์ BODY์ ๋ฌธ์ ๋ด์ฉ์ ์ง์ ๋ฐํ ํ๋ค!!)
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name) {
Hello hello = new Hello();
hello.setName(name); //parameter ๋ก ๋์ด์จ name์ ๋ฃ์ด์ค
return hello; // ๊ฐ์ฒด๋ฅผ ๋๊น!
}
static class Hello {
//class ์์์ ๋ class๋ฅผ ์ฌ์ฉํ ์ ์์!!
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ResponseBody ๋ฅผ ์ฌ์ฉํ๊ณ , ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฉด JSON์ผ๋ก ๋ณํ๋๋ค!
๋ค์ ์๋ฒ๋ฅผ ์ผ๋ณด๋ฉด!!
์๋ ๊ฒ json ์ด ๋ฑ์ฅํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค!
๋์ํ๋ ๋ฐฉ์์ ์ฐจ๋ก์ฐจ๋ก ์์๋ณด์..
์น ๋ธ๋ผ์ฐ์ ์์ localhost:8080/hello-api ๋ฅผ ๋๊ฒจ์ฃผ๋ฉด ํฐ์ผ ๋ด์ฅ ์๋ฒ์์ ์คํ๋ง์ hello-api ๋ฅผ ๋์ง๊ณ ~
Controller ์์ hello-api ๋ฅผ ์ฐพ์๋๋ฐ @ResponseBody ๊ฐ ์ ํ์์ผ๋ฏ๋ก
Spring์ viewResolver ์๊ฒ ํ ํ๋ฆฟ์ ์ฐพ์ผ๋ผ๊ณ ๋์ง๋๋ฐ ์ ํ์์ผ๋ฏ๋ก ๋ฐ๋ก Http ์๋ต์ ๊ทธ๋๋ก ๋ฃ์๊ฒ์ผ๋ก ๋์ํ๋ค.
return์ด ๋ฌธ์๋ผ๋ฉด http ์๋ต์ ๋ฐ๋ก ๋ฃ์ด์ ์ฃผ๋ฉด ๋์ง๋ง return ์ด ๊ฐ์ฒด๋ผ๋ฉด ๊ธฐ๋ณธ default ๊ฐ ๊ทธ๋ฅ json ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค์ด์ http ์๋ต์ ๋ฐํํ๊ฒ ๋๋ค!
→ ViewResolver ๊ฐ ์๋๋ผ HttpMesaageConverter ๊ฐ ๋์ํ๋ค (๋ง์ฝ ๋ฌธ์๋ผ๋ฉด , StringHttpMessageConverter ๊ฐ ๊ฐ์ฒด๋ผ๋ฉด, JsonConverter ๊ฐ ๋์ํจ)
๊ฐ๋จํ๊ฒ ๋ณด๋ฉด!!
@ResponseBody ๋ฅผ ์ฌ์ฉ?
→ HTTP์ BODY์ ๋ฌธ์ ๋ด์ฉ์ ์ง์ ๋ฐํ
→ viewResolver ๋์ ์ HttpMessageConverter ๊ฐ ๋์
→ ๊ธฐ๋ณธ ๋ฌธ์ ์ฒ๋ฆฌ : StringHttpMessageConverter
→ ๊ธฐ๋ณธ ๊ฐ์ฒด ์ฒ๋ฆฌ : MappingJackson2HttpMessageConverter
(Jackson ์ด๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ์ฒด๋ฅผ json์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ ์ญํ ์ด๋ค!
→ ์คํ๋ง์ ๊ธฐ๋ณธ ํ์ฌ)
→ byte ์ฒ๋ฆฌ ๋ฑ๋ฑ ๊ธฐํ ์ฌ๋ฌ HttpMessageConverter ๊ฐ ๊ธฐ๋ณธ์ผ๋ก ๋ฑ๋ก๋์ด ์์