๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

WINK-(Web & App)/Spring Boot ์Šคํ„ฐ๋””

[Spring Boot ์Šคํ„ฐ๋””] ํ•œ์ค€๊ต #1 ์ฃผ์ฐจ - ์„น์…˜ 1, 2 "๋‹ค์Œ๋ถ€ํ„ด ์š”์•ฝ์„ ํ•ด๋ณผ๊ฒŒ..."

๋ฐ˜์‘ํ˜•

๐ŸฆซSection 1. ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ์„ค์ •

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์ค€๋น„ํ•ด์•ผํ•  ๊ฒƒ.

  • Java 11 ์„ค์น˜ → ๋ฒ„์ „ ์ด์Šˆ ๋•Œ๋ฌธ์— Java 17
  • IDE (InteliJ) ์„ค์น˜

https://start.spring.io/

(์˜›๋‚ ์—๋Š” 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 ์„ ํ•จ)

ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • spring-boot-starter-test
    • junit : ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ
    • mockito : ๋ชฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    • assertj : ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ข€ ๋” ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    • spring-test : ์Šคํ”„๋ง ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ง€์›

Gradle ์˜ ๊ฒฝ์šฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ๋”ฐ์ ธ์„œ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•œ starter-web ๊ณผ starter-thymeleaf ์™ธ์—๋„ ์—ฌ๋Ÿฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!!

 

inteliJ ๋งจ ์˜ค๋ฅธ์ชฝ์— ๋ณด๋ฉด Gradle ์ด๋ผ๊ณ  ์žˆ๋Š”๋ฐ ํด๋ฆญํ•ด๋ณด๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ์Œ!

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐ•์˜๋Š” ๊ทธ๋ƒฅ ํ•œ๋ฒˆ ์ญ‰ ๋ณด์‹œ๋Š” ๊ฑฐ ์ถ”์ฒœ๋“œ๋ ค์š”…

(์ด๋Ÿฐ ๊ฒŒ ์žˆ๊ตฌ๋‚˜๋งŒ ์•Œ๊ณ  ๋„˜์–ด๊ฐ€๋ฉด ๋œ๋‹ต๋‹ˆ๋‹ค!!)

 

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

 

๋นŒ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ

๋นŒ๋“œ๋ฅผ ํ•ด์„œ ์‹ค์ œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ณด์ž!

 

ํ„ฐ๋ฏธ๋„์—

  1. ./gradlew build
  2. cd build/libs

  3. java -jar hello-spring-0.0.1-SNAPSHOT.jar

  4. ์‹คํ–‰ํ™•์ธ

์ˆœ์„œ๋กœ ์ง„ํ–‰!!

→ ๋‚˜์ค‘์— 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 ๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์Œ

 

๋ฐ˜์‘ํ˜•