์คํ๋ง์ ์ ์ Ch2. 02 Spring MVC
01. ์๊ฒฉ ํ๋ก๊ทธ๋จ์ ์คํ
๋ก์ปฌ ํ๋ก๊ทธ๋จ ์คํ

์๊ฒฉ ํ๋ก๊ทธ๋จ ์คํ
= ๋ค๋ฅธ ์ฌ๋์ ์ปดํจํฐ์ ์๋ ํ๋ก๊ทธ๋จ ์คํ
์คํ ๋ฐฉ๋ฒ
์๋ฒ์ ์๋ ์๊ฒฉ ํ๋ก๊ทธ๋จ์ ์คํํ๊ธฐ ์ํด์๋ ๋ธ๋ผ์ฐ์ ์ WAS๊ฐ ํ์ํ๋ค.
๋ธ๋ผ์ฐ์ ์์ http://111.222.333:8080์ URL ์ฃผ์๋ก ์์ฒญ์ ๋ณด๋ด๋ฉด,
ํฐ์บฃ์์ ์๊ฒฉ์ผ๋ก ํ๋ก๊ทธ๋จ(๋ฉ์๋)์ ์คํ์ํค๊ฒ๋๋ค.
์๋ฌด ํ๋ก๊ทธ๋จ์ด๋ ์๊ฒฉ ์คํ์ด ๊ฐ๋ฅํ ๊ฒ์ ์๋๋ค.
2. URL๊ณผ ๋ฉ์๋๋ฅผ ์ฐ๊ฒฐ(@RequestMapping)
@Controller // 1. ์๊ฒฉ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ฑ๋ก(AC์ ๋น์ผ๋ก ๋ฑ๋ก)
public class Hello {
@RequestMapping("/hello") // 2. URL๊ณผ main()์ ์ฐ๊ฒฐ / ์ด๊ฒ ์ค์ํ ๊ฑฐ์
private void main() { // ์ด๋ฆ์ ์๋ฌด๊ฑฐ๋ ์๊ด์์
System.out.println("Hello");
}
}
http://111.222.333.444:8080/ch2/hello ๋ฅผ ํธ์ถํ๋ฉด hello์ ์ฐ๊ฒฐ๋ ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
โURL์ ์ฐ๊ฒฐํ ๋ฉ์๋๊ฐ private์์๋ ํธ์ถ์ด ๊ฐ๋ฅํ ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
RequestMapping
์ ์ธ๋ถ์์
โ ์คํ๋ง ํ๋ ์์ํฌ๊ฐ ์๋ฐ์ Reflection API๋ฅผ ์ด์ฉํด์ ๊ฐ์ฒด๋ฅผ ์์ฑํด ๋ฉ์๋๋ฅผ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๋ค.
์์
package com.fastcampus.ch2; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws Exception { // Hello h = new Hello(); // h.main(); // main()์ private๋ผ์ ์ธ๋ถ ํธ์ถ ๋ถ๊ฐ // ์๊น๋ Reflection API(ํด๋์ค ์ ๋ณด๋ฅผ ์ป๊ณ ๋ค๋ฃฐ ์ ์๋ ๊ฐ๋ ฅ ๊ธฐ๋ฅ ์ ๊ณต)๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํธ์ถ์ด ๊ฐ๋ฅํ๋ ๊ฒ์ด๋ค. // java.lang.reflect ํจํค์ง ์ ๊ณต // Hello ํด๋์ค์ Class ๊ฐ์ฒด(ํด๋์ค์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด) ์ป์ด์จ๋ค. // ํด๋์ค ํ์ผ(*.class)์ด ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ ๋, ํด๋์ค ํ์ผ๋ง๋ค Class ๊ฐ์ฒด๊ฐ ํ๋์ฉ ์์ฑ๋๋ค. Class helloCass = Class.forName("com.fastcampus.ch2.Hello"); Hello hello = (Hello) helloCass.newInstance(); // Class ๊ฐ์ฒด๊ฐ ๊ฐ์ง ์ ๋ณด๋ก ๊ฐ์ฒด ์์ฑ Method main = helloCass.getDeclaredMethod("main"); // main() ๋ฉ์๋์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์จ๋ค. main.setAccessible(true); // private์ธ main()์ ํธ์ถ ๊ฐ๋ฅํ๊ฒ ํ๋ค. main.invoke(hello); // hello.main()๊ณผ ๋์ผ } }
โURL์ ์ฐ๊ฒฐํ๋ ๋ฉ์๋๋ ์ ์ธ์คํด์ค ๋ฉ์๋๋ก ์ ์ธํ๋ ๊ฑธ๊น?
โ static ๋ฉ์๋๋ iv๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ
+) URL๋ก ์๊ฒฉ ํ๋ก๊ทธ๋จ ํธ์ถ ์ ํฐ์บฃ์ด ๊ฐ์ฒด ์์ฑ์ ํด ์ค๋ค. ๊ทธ ๋ค์์ ๋ฉ์๋ ํธ์ถ์ด ๋๋ค.
์์
package com.fastcampus.ch2; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; // 1. ์๊ฒฉ ํธ์ถ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ฑ๋ก @Controller public class Hello { int iv = 10; // ์ธ์คํด์ค ๋ณ์ static int cv = 20; // static ๋ณ์ @RequestMapping("/hello") // 2. URL๊ณผ main()์ ์ฐ๊ฒฐ public void main() { // ์ธ์คํด์ค ๋ฉ์๋ - iv, cv๋ฅผ ๋ ๋ค ์ฌ์ฉ ๊ฐ๋ฅ System.out.println("Hello - private"); System.out.println(cv); // System.out.println(iv); } // ์ธ์คํด์ค ๋ฉ์๋์ ์คํํฑ ๋ฉ์๋์ ์ฐจ์ด๋ iv ์ฌ์ฉ ์ฌ public static void main2() { // static ๋ฉ์๋ - cv๋ง ์ฌ์ฉ ๊ฐ๋ฅ System.out.println(cv); // OK // System.out.println(iv); // ์๋ฌ static ๋ฉ์๋๋ ์ธ์คํด์ค ๋ฉค๋ฒ ์ฌ์ฉ ๋ถ๊ฐ๋ฅ } }
02. AWS์ ๋ฐฐํฌํ๊ธฐ
ํ๋ก์ ํธ war ํ์ผ๋ก ์ถ์ถ : Build > Build artifacts
13.124.20.48:8080/ch2/Hello
์๊ฒฉ ์๋ฒ์ ์ ์ํ๊ธฐ
03~04. HTTP ์์ฒญ๊ณผ ์๋ต
HttpServletRquest
@Controller // 1. ์๊ฒฉ ํธ์ถ์ด ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ฑ๋ก
public class RequestInfo {
@RequestMapping("/requestInfo") // 2. URL๊ณผ main()์ ์ฐ๊ฒฐ
public void main(HttpServletRequest request) {
System.out.println();
}
}
- http://localhost/requestInfo?bno=3 URL ์ ๋ ฅ ํ ํธ์ถ ์
- ํฐ์บฃ์ด HttpServletRequset ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
- ๊ฑฐ๊ธฐ์ ์์ฒญํ ์ ๋ณด๋ฅผ ๋ด๋๋ค.
- ํฐ์บฃ์ด main ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก ์์์ ๋๊ฒจ์ค๋ค.
์์ฒญ์ ๋ํ ์ ๋ณด๊ฐ ํ์ํ๋ฉด ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก HttpServletRequest๋ง ์ ์ด์ฃผ๋ฉด ๋๋ค. ๊ทธ๋ผ ์คํ๋ง์ด ์์์ ๋งค๊ฐ๋ณ์์ ํด๋นํ๋ ๊ฐ์ฒด๋ ๊ฐ์ ๋๊ฒจ์ค๋ค. request ์ฐธ์กฐ๋ณ์๋ฅผ ํตํด์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์ ๋ณด๋ฅผ ์ป์ด์ฌ ์ ์๋ค.
์ดํด๋ฅผ ๋๊ธฐ์ํ
YoilTeller.java
์์ terminal์์
java YoilTeller 2021 10 1
๋ก ํธ์ถํ๋ฉด ์๋ฐ ์ธํฐํ๋ฆฌํฐ๊ฐ ๋ฐฐ์ด์ 2021, 10, 1 ๊ฐ๋ค์ String ๋ฐฐ์ด์ ๋ด์์ main ๋ฉ์๋์ ๋งค๊ฐ๋ณ์์ ๋๊ฒจ์ค๋ค.์ด์ฒ๋ผ ์์ฒญํ ์ ๋ณด๋ฅผ ํฐ์บฃ์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ด์์ ๋๊ฒจ์ฃผ๋ ๊ฒ์ด๋ค. ์ฐ๋ฆฌ๋ ๋จ์ํ ๊ทธ๊ฑธ ์ฌ์ฉํ๋ฉด ๋๋ ๊ฒ์ด๋ค.
package com.fastcampus.ch2; import java.util.Calendar; // ๋ ์์ผ์ ์ ๋ ฅํ๋ฉด ํด๋น ๋ ์ง๊ฐ ์ด๋ค ์์ผ์ธ์ง ์๋ ค์ฃผ๋ ํ๋ก๊ทธ๋จ public class YoilTeller { public static void main(String[] args) { // 1. ์ ๋ ฅ String year = args[0]; String month = args[1]; String day = args[2]; int yyyy = Integer.valueOf(year); int mm = Integer.parseInt(month); int dd = Integer.parseInt(day); // 2. ์์ Calendar cal = Calendar.getInstance(); cal.set(yyyy, mm - 1, dd); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 : ์ผ์์ผ, 2 : ์์์ผ char yoil = " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek); // 3. ์ถ๋ ฅ System.out.printf("%d๋ %d์ %d์ผ์ ", yyyy, mm, dd); System.out.println(yoil + "์์ผ์ ๋๋ค."); } }
HttpServletRquest์ ๋ฉ์๋


?year=2021&month=10&day=1
// URL ์์ฒด๊ฐ ๋ฌธ์์ด์ด๊ธฐ ๋๋ฌธ์ ๋ฌธ์์ด๋ก ๋ฐ๋๋ก ๋์ด์๋ค.
String year = request.getParameter("year");
String year = request.getParameter("year");
String month = request.getParameter("month");
String day = request.getParameter("day");

์์ YoilTeller.java๋ฅผ ์๊ฒฉ ํธ์ถ์ด ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ณ๊ฒฝํ ์์
YoilTeller.java
http://localhost:8080/ch2/getYoil?year=2002&month=1&day=15
package com.fastcampus.ch2; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.Calendar; // ๋ ์์ผ์ ์ ๋ ฅํ๋ฉด ํด๋น ๋ ์ง๊ฐ ์ด๋ค ์์ผ์ธ์ง ์๋ ค์ฃผ๋ ํ๋ก๊ทธ๋จ // 1. ์๊ฒฉ ํธ์ถ์ด ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ณ๊ฒฝ @Controller public class YoilTeller { // public static void main(String[] args) { @RequestMapping("/getYoil") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ public void main(HttpServletRequest request, HttpServletResponse response) throws Exception { // 1. ์ ๋ ฅ String year = request.getParameter("year"); String month = request.getParameter("month"); String day = request.getParameter("day"); int yyyy = Integer.valueOf(year); int mm = Integer.parseInt(month); int dd = Integer.parseInt(day); // 2. ์์ Calendar cal = Calendar.getInstance(); cal.set(yyyy, mm - 1, dd); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 : ์ผ์์ผ, 2 : ์์์ผ char yoil = " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek); // 3. ์ถ๋ ฅ System.out.printf("%d๋ %d์ %d์ผ์ ", yyyy, mm, dd); System.out.println(yoil + "์์ผ์ ๋๋ค."); // ์ด๋ ๊ฒ ํ๋ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ๋ ๋ด๊ฐ ๋ณด๋ด๋ ๋ด์ฉ์ด ํ ์คํธ์ธ์ง ๋ฐ์ด๋๋ฆฌ์ธ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค. response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); // ์ด๊ฒ ์์ผ๋ฉด ํ๊ธ ๊นจ์ง๋ค. ์ฐ๋ฆฌ๊ฐ ๋ณด๋ด๋ ํ ์คํธ ์ธ์ฝ๋ฉ์ด ๋ฌด์์ธ์ง ์๋ ค์ค์ผ ๋ธ๋ผ์ฐ์ ๊ฐ ํด์ ๊ฐ๋ฅ PrintWriter out = response.getWriter(); // response ๊ฐ์ฒด์์ ๋ธ๋ผ์ฐ์ ๋ก์ ์ถ๋ ฅ ์คํธ๋ฆผ์ ์ป๋๋ค. out.printf("%d๋ %d์ %d์ผ์ ", yyyy, mm, dd); out.println(yoil + "์์ผ์ ๋๋ค."); } }
ํด๋ผ์ด์ธํธ์ ์๋ฒ
์๋ฒ(server) : ์๋น์ค(service)๋ฅผ ์ ๊ณตํ๋ ์ ํ๋ฆฌ์ผ์ด์

์๋ฒ์ ์ข ๋ฅ
์๋ฒ์ ์ข ๋ฅ๋ ์ด๋ค ์๋น์ค๋ฅผ ํ๋๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค.
์ด๋ฉ์ผ ์๋ฒ : ์ด๋ฉ์ผ ์๋น์ค ์ ๊ณต
ํ์ผ ์๋ฒ : ํ์ผ ์ ๊ณต
์น ์๋ฒ : ์น ์ ๊ณต?โย ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด์ ๋ฐ์ ์ ์๋ ๋ชจ๋ ์๋น์ค๋ฅผ ์ ๊ณต(๋ฌธ์, ์ด๋ฏธ์ง, ๋์์ ๋ชจ๋ ์น์๋ฒ๊ฐ ์ ๊ณตํ๋ ์๋น์ค๋ค.)

์๋ฒ์ ํฌํธ
1๋์ PC์ ์๋ฒ ํ๋ก๊ทธ๋จ์ด ์ฌ๋ฌ ๊ฐ ์กด์ฌํ ์ ์๋ค.
ํด๋ผ์ด์ธํธ๊ฐ IP๋ก ์์ฒญ ์ ํ ๋์ PC์ ์ฌ๋ฌ ๊ฐ์ ์๋ฒ๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ด๋ค ์๋ฒ์ ๋ํ ์์ฒญ์ธ์ง IP๋ก๋ง์ผ๋ก ๊ตฌ๋ถ์ ํ์ง ๋ชปํ๋ค.
์ด๋ ํ์ํ ๊ฒ์ด ํฌํธ ๋ฒํธ๋ค. ํฌํธ ๋ฒํธ๋ฅผ ์ ์ด์ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ํ๋ฉด ํ ๋์ PC์ค ์ด๋ค ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด๋ ๊ฑด์ง ์ ์ ์๋ค.

WAS(์น ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ)๋?
Web Server
: Web์ ์๋น์ค
Web Application Server
: Web Application์ ์๋น์ค โ Application์ ์๋น์ค โ ์ ํ๋ฆฌ์ผ์ด์
= ํ๋ก๊ทธ๋จ. WAS๋ ์๋ฒ์ ํ๋ก๊ทธ๋จ์ ์ค์นํด๋๊ณ ํด๋ผ์ด์ธํธ๊ฐ ์ด ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๊ฐ ๋ง๋ ํ๋ก๊ทธ๋จ์ ํด๋ผ์ด์ธํธ๊ฐ ์๊ฒฉ ํธ์ถํ๋ค.
์๋ ์๋ PC๋ง๋ค ๊ฐ๊ฐ ๋ค ํ๋ก๊ทธ๋จ์ ์ค์นํ์ด์ผ ํ๋ค. ๊ทธ๋ฐ๋ฐ Client์๊ฒ ์ค์นํ์ง ์๊ณ Server์๋ง ์ค์นํ๋ฉด ํ ๊ตฐ๋ฐ๋ง ์ ๋ฐ์ดํธํ๋ฉด ๋๋ค. ์ด๋ฐ ์ ๋ฐ์ดํธ์ ์ฉ์ด์ฑ ๋๋ฌธ์ WAS๋ฅผ ์ฌ์ฉํ๋ค.

Tomcat์ ๋ด๋ถ ๊ตฌ์กฐ

Thread Pool : ์ฐ๋ ๋๋ค์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋์๋ค๊ฐ ์์ฒญ์ด ์ค๋ฉด ์ด ์ค์ ํ๋์ ์ฐ๋ ๋๊ฐ ๋งก์์ ์์ฒญ์ ์ฒ๋ฆฌํ๋ค.
+) ๋ฏธ๋ฆฌ ์ฐ๋ ๋๋ฅผ ๋ง๋ค์ด๋์ผ๋ฉด ๊ทธ๋๊ทธ๋ ๋ง๋ค ํ์ X, ์์ฒญ์ด ์ค๋ฉด ํ๊ฐํ ์ฐ๋ ๋๊ฐ ์ฒ๋ฆฌํ๋ค.
Server
(Tomcat)์์ Service
๊ฐ ์๊ณ Service์์ ์ค์ ๋ก ์๋น์ค๋ฅผ ์ฒ๋ฆฌํ๋ Engine
์ด ์๋ค.
Connector
์ด๋ค protocol๋ก ์์ฒญํ๋์ ๋ฐ๋ผ ์ฒ๋ฆฌํ Connector
๊ฐ ๋ฌ๋ผ์ง๋ค.
Connector(HTTP1.1)์ Engine
์๊ฒ ์์ฒญ์ ์ ๋ฌํ๋ค.(์๋ฒ๊ฐ Tomcat์ด๋ฉด Engine์ด๋ฆ์ด Catalina)
Engine
Host
Engine ์์๋ Host๊ฐ ์๋ค. ๋ณดํต์ ํ๋์ง๋ง ํ๋์ ํฐ์บฃ ์์ ์ฌ๋ฌ ๊ฐ์ ํธ์คํธ๊ฐ ์กด์ฌํ ์ ์๋ค.(n๊ฐ์ ํธ์คํธ ๊ฐ๋ฅ)
Domain Name์ด ๋ค๋ฅธ ์ฌ๋ฌ ๊ฐ์ Host๋ฅผ ์ค์นํ ์ ์๋ค.
Context
Host ์์๋ Context๊ฐ ์๋๋ฐ ์ฌ๋ฌ ๊ฐ ์กด์ฌ ๊ฐ๋ฅํ๋ค.
Context = ํ๋์ ์น ์ ํ๋ฆฌ์ผ์ด์
ex) /ch2, /ch3 ์ด๋ ๊ฒ ์ฌ๋ฌ ๊ฐ์ ์ปจํ ์คํธ๊ฐ Host ์์ ์์ ์ ์๋ค.
ํ๋ํ๋๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ (์ฝ๊ฒ intelliJ ํ๋ก์ ํธ), ์๋ก ์ํฅ์ ์ฃผ์ง ์๋ ๋ ๋ฆฝ์ ์ธ ๊ณต๊ฐ์์ ๋์๊ฐ๋ค.
Servlet
Context ์์ ์๋ธ๋ฆฟ์ด ์กด์ฌํ๋ค. ์๋ธ๋ฆฟ์ ์์ ์๋ฒ ํ๋ก๊ทธ๋จ์ด๋ผ๋ ๋ป์ด๋ค.
์ปจํธ๋กค๋ฌ = ์๋ธ๋ฆฟ / ๋ ๋ค ์๋ฒ ํ๋ก๊ทธ๋จ
์์ฒญ URL์ด /event/list๋ฉด event ์ปจํ ์คํธ์ ํด๋นํ๋ list์ ์ฐ๊ฒฐ๋ ์๋ธ๋ฆฟ์ด ์คํ๋๋ค.
<์ ๋ฆฌ>
Tomcat Server
์์ Service
๊ฐ ์๊ณ ๊ทธ Service๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ Engine
Engine
์์๋ Host
๊ฐ ์ฌ๋ฌ ๊ฐ ์์ ์ ์๊ณ Host์์๋ Context
๊ฐ ์ฌ๋ฌ ๊ฐ ์์ ์ ์๋ค.
Context = Spring Project, ๊ทธ ์์ ์๋ ํ๋ก๊ทธ๋จ์ด Servlet
์ดํด๋ฅผ ๋๊ธฐ ์ํ ์์์ ์ค๋ช ํ ๊ณผ์ ์ดํด๋ณด๊ธฐ
์ฐ๋ ๋๊ฐ ์ฌ๋ฌ๊ฐ ์๋๋ฐ ๊ทธ ์ค์ ํ๋๊ฐ ์์ฒญ์ ๋ฐ์์ ์ฒ๋ฆฌํ ๊ฒ
ํธ์ถ์คํ์ด ์๋๋ถํฐ ์ญ ์์ธ ๊ฑด๋ฐ ์ ์ผ ์๋ run๋ถํฐ ์์ํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด ์์ฒญ์
HTTP 1.1 Prosessor
๊ฐ ์ฒ๋ฆฌ๊ฐ๋ณ๊ฒ ๋ณด๊ธฐ์ด๋ฐ์์ผ๋ก ํ๋ฌ๊ฐ๋๊ตฌ๋ ์ ๋๋ง ์๋ฉด๋จ
HTTP 1.1
๊ฐ ์์ฒญ์ ๋ฐ์์ ์์ฒญ ์ ๋ณด๋ฅผ request์ ๋ด๊ณ , response๋ฅผ ๋ง๋ค์ด์ ์ค๋ค. ๊ทธ ์์ ์ด ์ฌ๊ธฐ๋ค.์์ฒญ์ด ์ค๋ฉด ์ฐ๋ ๋ ํ์์(์ฐ๋ ๋๋ค์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋๋๋ค. Why? ์์ฒญ ์์ ๋ ๋ง๋ค๋ฉด ๋๋ฆฌ๋๊น) ํ๊ฐํ ์ฐ๋ ๋๊ฐ ์์ฒญ์ ๋ฐ์์ ์ฒ๋ฆฌํ๋ค. ๊ทธ๋ฆฌ๊ณ ํ๋กํ ์ฝ์ ๋ฐ๋ผ์ ์ฐ๊ฒฐํ๋ค.(HTTP ํ๋กํ ์ฝ์ด๋ฉด 1.1์ด ๋ฐ๊ณ ..)
Dispatcher Servlet
์ด Controller์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
Tomcat์ ์ค์ ํ์ผ - server.xml, web.xml
ํฐ์บฃ์ค์น๊ฒฝ๋ก/conf/web.xml : Tomcat์ ๋ชจ๋ web app์ ๊ณตํต ์ค์
์น์ฑ์ด๋ฆ/WEB-INF/web.xml : web app์ ๊ฐ๋ณ ์ค์
โป web app = ์น ์ ํ๋ฆฌ์ผ์ด์
HTTP ์์ฒญ๊ณผ ์๋ต
1. ํ๋กํ ์ฝ(protocol)์ด๋?
์ฃผ๊ณ ๋ฐ์ Data์ ๋ํ ํ์์ ์ ์ํ ๊ฒ
Data๋ฅผ ์ด๋ป๊ฒ ์ฃผ๊ณ ๋ฐ์์ง ๋ฏธ๋ฆฌ ์ฝ์ํ์ง ์์ผ๋ฉด Data๋ฅผ ๋ฐ์๋ ์ด๊ฒ ์ด๋ค ๋ด์ฉ์ธ์ง ํด์ํ ์ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๋ค ํ์์ผ๋ก Data๋ฅผ ์ฃผ๊ณ ๋ฐ์์ง ๋ฏธ๋ฆฌ ์ฝ์ํด์ผ ํ๋ค.
์๋ก์ ์ํต์ ์ํด์ ๋ฏธ๋ฆฌ ์ ํด๋์ ๊ท์น = ํ๋กํ ์ฝ
โ ๊ทธ๋ฅ ์ฝ๊ฒ ํ๋กํ ์ฝ์ ์ฝ์, ๊ท์น
์ด๋ผ๊ณ ์ธ์ฐ์!
<์ดํด๋ฅผ ๋๊ธฐ์ํ ์ค์ํ์์์ ์>
ํธ์ง์ ๋ณด๋ด๋ ์ฌ๋ ์์น, ๋ฐ๋ ์ฌ๋ ์์น, ์ฐํ ์์น ์ด๋ฐ ๊ฒ๋ค์ด ๋ฐ๋ก ํ๋กํ ์ฝ์ด๋ค.
ํธ์ง๋ฅผ ๋ณด๋ด๋ ์ฌ๋, ๋ฐ๋ ์ฌ๋, ๋ฐฐ๋ฌ ํ๋ ์ฌ๋๋ผ๋ฆฌ ์ด๋ฐ ํ๋กํ ์ฝ(์ฌํ์ ์ธ ํฉ์)์ด ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๊ฐ ๋ณ๋ค๋ฅธ ์ค๋ช ์์ด ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด๋ค.
2. HTTP(Hyper Text Transfer Protocol)๋?
ํ ์คํธ ์ ์ก ํ๋กํ ์ฝ
โ ํ ์คํธ๋ฅผ ์ ์กํ๊ธฐ ์ํ ํ๋กํ ์ฝ(์ฝ์, ๊ท์น)
โป Hyper Text = HTML
<ํน์ง>
- ๋จ์ํ๊ณ ์ฝ๊ธฐ ์ฝ๋ค. - ํ ์คํธ ๊ธฐ๋ฐ์ ํ๋กํ ์ฝ
- ์ํ๋ฅผ ์ ์งํ์ง ์๋๋ค.(stateless) - Client ์ ๋ณด๋ฅผ ์ ์ฅX
๊ฐ์ Client๊ฐ ์์ฒญ์ ๋ ๋ฒ ๋ณด๋์ ๋ Server๋ ์ด ๋ ์์ฒญ์ด ๊ฐ์ Client๊ฐ ๋ณด๋ธ ๊ฒ์ธ์ง ๊ตฌ๋ณ ๋ชปํ๋ค.
Why? ํด๋ผ์ด์ธํธ ์ ๋ณด๋ฅผ ์ ์ฅํ์ง ์๊ธฐ ๋๋ฌธ์
โ ์ด๋ฐ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฟ ํค์ ์ธ์ ์ด๋ค.(ํด๋ผ์ด์ธํธ ๊ตฌ๋ณ ๊ฐ๋ฅํ๊ฒ๋จ)
3. HTTP ๋ฉ์์ง
ํธ์งํ๊ณ ๋น์ทํ๋ค. ๋ ๋ค ํ ์คํธ์ด๋ค.
ํค๋ = ๋ณธ๋ฌธ์ ๋ํ ์ค๋ช | ํธ์ง์ ๋ํ ์ค๋ช .
๋ฐ๋ = ์ค์ ์ ๋ฌํ ๋ด์ฉ.
HTTP ํ๋กํ ์ฝ์ ์๋ก์๊ฒ ์์ฒญ ํธ์ง๋ฅผ ๋ณด๋ด๊ณ , ์๋๋ฐฉ์ ์์ฒญ์ ๋ํ ์๋ต ํธ์ง๋ฅผ ๋ณด๋ธ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.

์ฐ๋ฆฌ๋ URL๋ง ์ ๋ ฅํ์ง๋ง ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ๊ทธ๋ฆผ์ฒ๋ผ HTTP ์์ฒญ ๋ฉ์์ง๋ฅผ ๋ง๋ค์ด์ ์๋ฒ์๊ฒ ์ ์กํด์ค๋ค.
์๋ต ๋ด์ฉ์ด ๋ธ๋ผ์ฐ์ ์ Hello๋ผ๊ณ ํด์๋์ด ๋์ค๋ ๊ฒ์ด๋ค.

HTTP ๋ฉ์์ง - ์๋ต ๋ฉ์์ง
HTTP ์๋ต ๋ฉ์์ง foramt์ ๋ง์ถฐ์ ์ค์ผ Client๊ฐ ๋ด์ฉ์ ์ดํดํ ์ ์๋ค.

์ํ ๋ผ์ธ = ์์ฒญ์ด ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋์๋์ง ์๋ ค์ค๋ค.
์ํ ์ฝ๋ ์์๋ ์ค๋ช
์๋์ ๊ธฐ๋ณธ์ ์ธ ์ํ์ฝ๋๋ ์ธ์์ผ ํ๋ค.
HTTP ์ํ์ฝ๋ | ์๋ฏธ | ์์ธ ์ค๋ช |
---|---|---|
1xx | Informational | HTTP/1.1 ์ถ๊ฐ ์ ๋ณด ๊ตํ |
2xx | Success | ์ฑ๊ณต |
3xx | Redirect | ๋ค๋ฅธ URL ์์ฒญ |
4xx | Client Error | ํด๋ผ์ด์ธํธ ์๋ชป |
5xx | Server Error | ์๋ฒ ์๋ชป |
400๋ฒ๋ - Client Error
ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญ์ ์๋ชปํ ๊ฒ์ด๋ค. ์๋ฒ๋ ์๋ชปํ ๊ฒ X
๋ด๊ฐ ์์ฒญํ ๋ฆฌ์์ค๋ฅผ ์ฐพ์ ์ ์์
500๋ฒ๋ - Server Error
ํด๋ผ์ด์ธํธ ์๋ชปX. ์๋ฒ ์๋ชป.
๋๋ ์์ฒญ์ ์ ๋๋ก ํ๋๋ฐ ์์ฒญ์ ์ฒ๋ฆฌํ๋ค๊ฐ ํ๋ก๊ทธ๋จ์ ๋ฌธ์ ๊ฐ ์์ด์ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค.

HTTP ๋ฉ์์ง - ์์ฒญ ๋ฉ์์ง
์ข ๋ฅ(๋ํ์ ์ธ ๊ฑฐ ๋๊ฐ๋ง)
GET
- read๋จ์ํ ์๋ฒ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์จ๋ค. ์ฆ ์ฝ๊ธฐ.
๋ฆฌ์์ค URL๋ง ์ ์ด์ฃผ๋ฉด ๋์ด์ ๋ฐ๋๊ฐ ํ์์๊ณ ํค๋๋ง ์กด์ฌํ๋ค.
Data๋ฅผ ๋ณด๋ผ ๊ฒ ์์ผ๋ฉด ์ฟผ๋ฆฌ ์คํธ๋ง์ผ๋ก ๋ณด๋ผ ์ ์๋ค.
POST
- write or ์๋ฒ์ ๋ฐ์ดํฐ ์ ๊ณตwrite, ๊ธ์ฐ๊ธฐ, ํ์๊ฐ์ , ํ์ผ ์ฒจ๋ถ, ์๋ฒ์ Data ์ ๊ณต ์ด๋ฐ ์ฉ๋๋ก ๋ง๋ค์ด์ง ๊ฒ์ด๋ค.
POST๊ฐ์ ๊ฒฝ์ฐ๋ body๊ฐ ์์ด์ GET์์ ์ผ๋ ์ฟผ๋ฆฌ ์คํธ๋ง์ด body์ ๋ค์ด๊ฐ๋ค.
โ ์๋ฒ์ ์ ์กํ Data๋ฅผ body์ ๋ด๋๋ค.
HTTP ๋ฉ์๋ - GET, POST
GET | POST | |
---|---|---|
์ค๊ณ ๋ชฉ์ | ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ค๊ณ | ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฆฌ๊ธฐ ์ํด ์ค๊ณ |
๋ฐ์ดํฐ ์ ์ก | Query String์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ(์์ฉ๋) | ์ ์ก ๋ฐ์ดํฐ ํฌ๊ธฐ์ ์ ํ์ด ์์(๋์ฉ๋) |
๋ณด์ | URL์ ๋ฐ์ดํฐ ๋ ธ์ถ๋๋ฏ๋ก ๋ณด์์ ์ทจ์ฝ | ๋ฐ์ดํฐ๋ฅผ ์์ฒญ ๋ฉ์์ง์ body์ ๋ด์ ์ ์ก โ ๋ณด์์ ์ ๋ฆฌ |
๋ฐ์ดํฐ ๊ณต์ | ๋ฐ์ดํฐ ๊ณต์ ์ ์ ๋ฆฌ | ๋ฐ์ดํฐ ๊ณต์ ์ ๋ถ๋ฆฌ |
๊ทธ๋ฅ ๋จ์ํ POST ๋ฐฉ์์ด๋ผ๊ณ ํด์ ๋ณด์์ ์ ๋ฆฌํ ๊ฒ ์๋๋ผ
HTTP
+ TLS
(์ํธํ ํ๋กํ ์ฝ) โ HTTPS
์ฌ์ผ ๋ณด์์ ์ ๋ฆฌํ ๊ฒ์ด๋ค. TLS ์์ด POST๋ก ๋ณด๋๋ค๊ณ ๋ณด์์ ์ ๋ฆฌํ์ง๋ ์๋ค.
SSL(old) โ TLS(new)
๋ณด์ ํ๋กํ ์ฝ
๊ฐ๋ฐ์ ๋๊ตฌ๋ก ์์ฒญ ํค๋ ์ดํด๋ณด๊ธฐ
๊ฐ๋ฐ์๋๊ตฌ ์ผ ์ํ์์ ์๋ก๊ณ ์นจํ๊ณ ๋คํธ์ํฌ โ getYoil ๋๋ฅด๋ฉด ์์ฒญ์ ๋ํ ํค๋๋ฅผ ๋ณผ ์ ์๋ค.
๋ทฐ ์์ค ๋๋ฅด๋ฉด ์๋ ์์ฒญ์ด ์ด๋ป๊ฒ ๊ฐ๋์ง ๋ณผ ์ ์๋ค.
General ํค๋๋ ์์ฒญ ํค๋, ์๋ต ํค๋๋ฅผ ์ ์ธํ ์ผ๋ฐ์ ์ธ ํค๋์ด๋ค.(์์ฒญ๊ณผ ์๋ต์ ๊ณตํต์ ์ธ ํค๋)
Response ํญ์ ๋๋ฅด๋ฉด ์๋ต์ ๋ณผ ์ ์๋ค.
ํ ์คํธ ํ์ผ VS ๋ฐ์ด๋๋ฆฌ ํ์ผ
๋ฌธ์
+ ์ซ์
๊ฐ ์ ์ฅ๋์ด ์๋ ํ์ผํ
์คํธ ํ์ผ : ๋ฌธ์
๋ง ์ ์ฅ๋์ด์๋ ํ์ผ
์๋๋ image.jpg๋ผ๋ ์ด๋ฏธ์ง ํ์ผ์ ๋ฉ๋ชจ์ฅ์ผ๋ก ์ฐ ๊ฒ์ด๋ค.
๋ฉ๋ชจ์ฅ์ผ๋ก ์ด์์ ๋ ์ฝ์ ์ ์์ผ๋ฉด ํ ์คํธ ํ์ผ, ์ฝ์ ์ ์์ผ๋ฉด ๋ฐ์ด๋๋ฆฌ ํ์ผ์ด๋ค.
๋ฐ์ด๋๋ฆฌ ํ์ผ : ๋ฐ์ดํฐ๋ฅผ ์๋ ๊ทธ๋๋ก ์ฝ๊ณ ์ด๋ค.
ํ ์คํธ ํ์ผ : ์ซ์๋ฅผ ๋ฌธ์๋ก ๋ณํ ํ ์ด๋ค.
ํ์ผ ์ข ๋ฅ | ์ฐ๊ธฐ | ์ฝ๊ธฐ |
---|---|---|
๋ฐ์ด๋๋ฆฌ | ๋ฌธ์ โ ๋ฌธ์ ์ซ์ โ ์ซ์ | ๋ฌธ์ โ ๋ฌธ์ ์ซ์ โ ์ซ์ |
ํ ์คํธ | ๋ฌธ์ โ ๋ฌธ์ ์ซ์ โ ๋ฌธ์ | ๋ฌธ์ โ ๋ฌธ์ |
8. MIME(Multipurpost Internet Mail Extensions)
HTTP๋ ํ ์คํธ ๊ธฐ๋ฐ์ด๋ค.(HTTP = Hyper Text Transfer Protocol) ๊ทธ๋ผ ํ ์คํธ๋ฐ์ ์ ์ก์ ๋ชปํ ๊น? ์๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฏธ ๋ธ๋ผ์ฐ์ ์์ ์ด๋ฏธ์ง, ๋์์(๋ฐ์ด๋๋ฆฌ ํ์ผ)์ ๋ค ๋ณด๊ณ ์๋ค.
ํ ์คํธ ๊ธฐ๋ฐ ํ๋กํ ์ฝ์์ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ์ ์กํ ๊น? MIME(์ ์กํ ๋ฐ์ดํฐ์ ํ์ )์ ์ ์ด์ฃผ๋ฉด ๋๋ค.
ex ) response.setContentType("text/html");
ํ์ | ์ค๋ช | MIMEํ์ ์์(ํ์ /์๋ธํ์ ) |
---|---|---|
text | ํ ์คํธ๋ฅผ ํฌํจํ๋ ๋ชจ๋ ๋ฌธ์ | text/plain, text/html, text/css, text/javascript |
image | ๋ชจ๋ ์ข ๋ฅ์ ์ด๋ฏธ์ง | image/bmp, image/webp |
audio | ๋ชจ๋ ์ข ๋ฅ์ ์ค๋์ค ํ์ผ | audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav |
video | ๋ชจ๋ ์ข ๋ฅ์ ๋น๋์ค ํ์ผ | video/webm, video/ogg |
application | ๋ชจ๋ ์ข ๋ฅ์ ์ด์ง ๋ฐ์ดํฐ | application/octetstream, application/pkcs12, application/vnd.mspowerpoint, application/xhtml+xml, application/xml, application/pdf |
์์ 1 : RequestHeader(์ค์ ๋ก ๋ด๊ฐ ์์ฒญํ๊ฒ ์ด๋ค ๋ด์ฉ, ์ด๋ค ํค๋๋ก ๊ฐ๋์ง ํ์ธ)
package com.fastcampus.ch2; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; @Controller // 1. ์๊ฒฉ ํธ์ถ ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ฑ๋ก public class RequestHeader { @RequestMapping("/requestHeader") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ public void main(HttpServletRequest request) { Enumeration<String> e = request.getHeaderNames(); while (e.hasMoreElements()) { String name = e.nextElement(); // ์์ฒญ ํค๋์ ์ด๋ฆ์ ๋์๋ฌธ์ ๊ตฌ๋ถํ์ง ์๋๋ค. System.out.println(name + ":" + request.getHeader(name)); } } }
์์ 2 : ํค๋๋ฟ ์๋๋ผ ๋ฉ์์ง ์ ์ฒด๋ฅผ ๋ณด์ฌ์ฃผ๋ ์์
package com.fastcampus.ch2; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class RequestMessage { @RequestMapping("/requestMessage") public void main(HttpServletRequest request) throws Exception { // 1. request line String requestLine = request.getMethod(); // GET ๋๋ POST requestLine += " " + request.getRequestURI(); // /ch2/requestMessage ์ด๊ฑด ์์ฃผ ์ฌ์ฉํ๋ ์ ์์๋ ๊ฒ String queryString = request.getQueryString(); // year=2021&month=10&day=1 requestLine += queryString == null ? "" : "?" + queryString; requestLine += " " + request.getProtocol(); // HTTP/1.1 System.out.println(requestLine); // 2. request headers Enumeration<String> e = request.getHeaderNames(); while (e.hasMoreElements()) { String name = e.nextElement(); System.out.println(name + ":" + request.getHeader(name)); } // 3. request body - POST์ผ ๋๋ง ํด๋น, GET์ body๊ฐ ์์(CONTENT_LENGTH=0) final int CONTENT_LENGTH = request.getContentLength(); // System.out.println("content length="+CONTENT_LENGTH); if (CONTENT_LENGTH > 0) { byte[] content = new byte[CONTENT_LENGTH]; InputStream in = request.getInputStream(); in.read(content, 0, CONTENT_LENGTH); System.out.println(); // empty line System.out.println(new String(content, "utf-8")); // year=2021&month=10&day=1 } // if } // main }
9. Base64
: ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํ ์คํธ ๋ฐ์ดํฐ๋ก ๋ณํํ ๋ ์ฌ์ฉํ๋ค.
2์ง๋ฒ = base2 = 0, 1
10์ง๋ฒ = base10 = 0~9
16์ง๋ฒ = base16 = 0~9 ABCDEF
64์ง๋ฒ = A~Z, a-z, 0~9, +, / โ ๋ชจ๋ 64๊ฐ(6 bit)์ ๋ฌธ์๋ก ๊ตฌ์ฑ
<๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํ ์คํธ ๊ธฐ๋ฐ์ธ HTTP ํ๋กํ ์ฝ๋ก ๋ณด๋ด๋ ๋ฐฉ๋ฒ>
- MIME์ผ๋ก ๋ฐ์ด๋๋ฆฌ ๊ทธ๋๋ก ๋ณด๋ด๊ธฐ
- Base64๋ก ๋ฐ์ด๋๋ฆฌ๋ฅผ ํ
์คํธ๋ก ๋ณํํด์ ๋ณด๋ธ๋ค.
๋จ์ : Data์ ์ฌ์ด์ฆ๊ฐ ์ปค์ง๋ค.


2. ๊ณตํต ์ฝ๋์ ๋ถ๋ฆฌ - ์ ๋ ฅ์ ๋ถ๋ฆฌ


3. ์ถ๋ ฅ(view)์ ๋ถ๋ฆฌ - ๋ณํ๋ ๊ฒ๊ณผ ๋ณํ์ง ์๋ ๊ฒ์ ๋ถ๋ฆฌ

4. MVC ํจํด
์คํ๋ง MVC๊ฐ ์ด๋ฐ ๊ตฌ์กฐ๋ก ๋์ด์๋ค.
DispatcherServlet
์ด ์์์ ์
๋ ฅ์ฒ๋ฆฌ, Model
(๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ ๊ฐ์ฒด)์ ๋ง๋ ๋ค์์ ๊ทธ๊ฑธ Controller
์๊ฒ ๋๊ฒจ์ค๋ค. Controller
๊ฐ ๊ทธ๊ฑธ ๋ฐ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํด์ ์ฃผ๋ฉด ๊ทธ๊ฑธ View
ํํ
์ ๋ฌํด์ค๋ค. ๋ทฐ์์๋ ์์
ํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์ต์ข
์๋ต์ ๋ง๋ค์ด์ Client์๊ฒ ๋ณด๋ธ๋ค.


์ฌ์ฉ์๊ฐ ์ ํํ ๋ทฐ๋ก ๋ณด์ฌ์ค๋ค.
<MVC>
- ์ ๋ ฅ๋ฐ์ ๊ฐ๋ค์ ๋งค๊ฐ๋ณ์๋ก ์ ์ธ.
- Model์ ์ ์ธํด์ ์์ ์ ์ฒ๋ฆฌ
- Model์ ์์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅ
- ์ด ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค View ๋ฐํ
- DispatcherServlet์ด ์์ฑ ๊ฒฐ๊ณผ๊ฐ ์ ์ฅ๋์ด์๋ Model์ View์๋ค ์ ๋ฌ.
- ๊ทธ๋์ View๋ Data๊ฐ ๋ด๊ฒจ์๋ Model ๊ฐ์ฒด์์ ๊ฐ์ ์ฝ์ ์ ์๋ ๊ฒ์ด๋ค.
+) ์ค์ต
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
// ๋
์์ผ์ ์
๋ ฅํ๋ฉด ํด๋น ๋ ์ง๊ฐ ์ด๋ค ์์ผ์ธ์ง ์๋ ค์ฃผ๋ ํ๋ก๊ทธ๋จ
// 1. ์๊ฒฉ ํธ์ถ์ด ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ณ๊ฒฝ
@Controller
public class YoilTeller {
// public static void main(String[] args) {
@RequestMapping("/getYoil") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ
public void main(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1. ์
๋ ฅ
String year = request.getParameter("year");
String month = request.getParameter("month");
String day = request.getParameter("day");
int yyyy = Integer.valueOf(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
// 2. ์์
Calendar cal = Calendar.getInstance();
cal.set(yyyy, mm - 1, dd);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 : ์ผ์์ผ, 2 : ์์์ผ
char yoil = " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek);
// 3. ์ถ๋ ฅ
System.out.printf("%d๋
%d์ %d์ผ์ ", yyyy, mm, dd);
System.out.println(yoil + "์์ผ์
๋๋ค.");
// ์ด๋ ๊ฒ ํ๋ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ๋ ๋ด๊ฐ ๋ณด๋ด๋ ๋ด์ฉ์ด ํ
์คํธ์ธ์ง ๋ฐ์ด๋๋ฆฌ์ธ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.
response.setContentType("text/html");
response.setCharacterEncoding("utf-8"); // ์ด๊ฒ ์์ผ๋ฉด ํ๊ธ ๊นจ์ง๋ค. ์ฐ๋ฆฌ๊ฐ ๋ณด๋ด๋ ํ
์คํธ ์ธ์ฝ๋ฉ์ด ๋ฌด์์ธ์ง ์๋ ค์ค์ผ ๋ธ๋ผ์ฐ์ ๊ฐ ํด์ ๊ฐ๋ฅ
PrintWriter out = response.getWriter(); // response ๊ฐ์ฒด์์ ๋ธ๋ผ์ฐ์ ๋ก์ ์ถ๋ ฅ ์คํธ๋ฆผ์ ์ป๋๋ค.
out.printf("%d๋
%d์ %d์ผ์ ", yyyy, mm, dd);
out.println(yoil + "์์ผ์
๋๋ค.");
}
}
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Calendar;
// ๋
์์ผ์ ์
๋ ฅํ๋ฉด ํด๋น ๋ ์ง๊ฐ ์ด๋ค ์์ผ์ธ์ง ์๋ ค์ฃผ๋ ํ๋ก๊ทธ๋จ
// 1. ์๊ฒฉ ํธ์ถ์ด ๊ฐ๋ฅํ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ณ๊ฒฝ
@Controller
public class YoilTellerMVC { // http://l
// public static void main(String[] args) {
@RequestMapping("/getYoilMVC") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ
// public void main(HttpServletRequest request, HttpServletResponse response) throws Exception {
public String main(int year, int month, int day, Model model) throws Exception {
// 1. ์ ํจ์ฑ ๊ฒ์ฌ
if (!isValid(year, month, day))
return "yoilError";
// 2. ์์ผ ๊ณ์ฐ
char yoil = getYoil(year, month, day);
// 3. ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ model์ ์ ์ฅ
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", day);
model.addAttribute("yoil", yoil);
return "yoil";
}
private boolean isValid(int year, int month, int day) {
return true;
}
private char getYoil(int year, int month, int day) {
Calendar cal = Calendar.getInstance();
cal.set(year, month - 1, day);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1 : ์ผ์์ผ, 2 : ์์์ผ
return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek);
}
}
servlet-context.xml
(์น ๊ด๋ จ๋ ์ค์ ํ์ผ) +) root-context.xml : ์น ๊ด๋ จ๋์ง ์์ ์ค์ ํ์ผ
prefix = ์ ๋์ฌ, view์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๊ณณ
suffix = ์ ๋ฏธ์ฌ

์ด ์ค์ ๋๋ถ์ View์ ์ด๋ฆ๋ง ๋ฐํํด์ฃผ์ด๋ ์์ ๊ฒฝ๋ก๊ฐ ๋ถ๊ณ , ๋ค์ ํ์ฅ์๊ฐ ๋ถ๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ๊ณตํต ๋ถ๋ถ์ ๋ถ๋ฆฌํด๋์ผ๋ฉด ๋์ค์ ๋ณ๊ฒฝ์ฌํญ(ex. view ๊ฒฝ๋ก ๋ณ๊ฒฝ)์ด ์๊ฒผ์ ๋ ์ฝ๊ฒ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค.
5. ModelAndView

6. ์ปจํธ๋กค๋ฌ ๋ฉ์๋์ ๋ฐํํ์

<์ปจํธ๋กค๋ฌ ๋ฉ์๋์ ๋ฐํํ์ >
- ๋ทฐ์ ์ด๋ฆ ๋ฐํ O โ ์ด๊ฑฐ๋ฅผ ์ ์ผ ๋ง์ด ์ด๋ค.
- ๋ทฐ์ ์ด๋ฆ ๋ฐํ X
๋ทฐ์ ์ด๋ฆ์ ๋ฐํํด์ฃผ์ง ์์ผ๋ฉด ๋งคํ๋ url์ ์ํด์ View์ ์ด๋ฆ์ด ๊ฒฐ์ ๋๋ค.(๋งคํ๋ ์ฃผ์.jsp๋ก ํด์๋๋ค.)
์ด๋ ๊ฒ๋ ์ ์ ์ฐ์ง๋ง ๊ฐ๋ฅํ๋ค๋ ๊ฒ๋ง ์์์ฃผ์.
์์ ์ฝ๋
@RequestMapping("/getYoilMVC") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ // public void main(HttpServletRequest request, HttpServletResponse response) throws Exception { public void main(int year, int month, int day, Model model) throws Exception { // 1. ์ ํจ์ฑ ๊ฒ์ฌ // if (!isValid(year, month, day)) // return "yoilError"; // 2. ์์ผ ๊ณ์ฐ char yoil = getYoil(year, month, day); // 3. ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ model์ ์ ์ฅ model.addAttribute("year", year); model.addAttribute("month", month); model.addAttribute("day", day); model.addAttribute("yoil", yoil); // return "yoil"; }
- ModelAndView
์์ฃผ ์ฌ์ฉํ๋ ํธ์ ์๋. ์๋ค๋ ๊ฒ๋ง ์์๋์
์ฝ๋
@RequestMapping("/getYoilMVC") // 2. URL๊ณผ ๋ฉ์๋ ์ฐ๊ฒฐ // public void main(HttpServletRequest request, HttpServletResponse response) throws Exception { public ModelAndView main(int year, int month, int day) throws Exception { ModelAndView mv = new ModelAndView(); // 1. ์ ํจ์ฑ ๊ฒ์ฌ // if (!isValid(year, month, day)) // return "yoilError"; // 2. ์์ผ ๊ณ์ฐ char yoil = getYoil(year, month, day); // 3. ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ model์ ์ ์ฅ mv.addObject("year", year); mv.addObject("month", month); mv.addObject("day", day); mv.addObject("yoil", yoil); // 4. ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค view๋ฅผ ์ง์ mv.setViewName("yoil"); return mv; // return "yoil"; }
+) MVC ํจํด์ ์๋ฆฌ
๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์ป๋ ๋ฐฉ๋ฒ
- ๋ฆฌํ๋ ์
API
-parameters ์ต์ ์ ๋ฃ๊ณ ์ปดํ์ผ์ ํด์ผ ํ๋ค. jdk1.8๋ถํฐ ๊ฐ๋ฅ
javac -parameters ๋ช ๋ น์ด์์ -parameters ์ต์ ์ด ๋น ์ง๋ฉด ํด๋์คํ์ผ์ ๋งค๊ฐ๋ณ์์ด๋ฆ์ ์ ์ฅํ์ง์๋๋ค
- Class file
MethodInfo.java
package com.fastcampus.ch2; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.StringJoiner; public class MethodInfo { public static void main(String[] args) throws Exception { // 1. YoilTeller ํด๋์ค์ ๊ฐ์ฒด๋ฅผ ์์ฑ Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC"); Object obj = clazz.newInstance(); // 2. ๋ชจ๋ ๋ฉ์๋ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ฐฐ์ด์ ์ ์ฅ Method[] methodArr = clazz.getDeclaredMethods(); for (Method m : methodArr) { String name = m.getName(); // ๋ฉ์๋์ ์ด๋ฆ Parameter[] paramArr = m.getParameters(); // ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก // Class[] paramTypeArr = m.getParameterTypes(); Class returnType = m.getReturnType(); // ๋ฐํ ํ์ StringJoiner paramList = new StringJoiner(", ", "(", ")"); for (Parameter param : paramArr) { String paramName = param.getName(); Class paramType = param.getType(); paramList.add(paramType.getName() + " " + paramName); } System.out.printf("%s %s%s%n", returnType.getName(), name, paramList); } } // main } /* [์คํ๊ฒฐ๊ณผ] java.lang.String main(java.lang.String year, java.lang.String month, java.lang.String day, org.springframework.ui.Model model) boolean isValid(int year, int month, int day) */
ํ๋ฉด์ ๋ณด์ฌ์ฃผ๋ ๋ถ๋ถ JSP์ ์๋ฆฌ, ์ดํด
JSP๋ ์๋์ ๊ฐ์ด ๋์ด์๋ ๊ฒ์ด๋ค. view๋ฅผ ์ฌ๋ฌ๊ฐ ๋ง๋ค์ด๋๊ณ view์ด๋ฆ์ ๋ค๋ฅด๊ฒ ๋ฐํํ๋ฉด view์ ๋ง๊ฒ ๊ฐ๋ค์ ์ฑ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค.
MethodCall.java
package com.fastcampus.ch2; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Scanner; import java.util.Set; class ModelController { public String main(HashMap map) { map.put("id", "asdf"); map.put("pwd", "1111"); return "txtView1"; } } public class MethodCall { public static void main(String[] args) throws Exception { HashMap map = new HashMap(); System.out.println("before:" + map); // ์ปจํธ๋กค๋ฌ๋ฅผ ์ง์ ์์ฑํ๊ณ ๋ฉ์๋๋ฅผ ํธ์ถ. ModelController mc = new ModelController(); String viewName = mc.main(map); System.out.println("after :" + map); // ์์ ๊ฒฐ๊ณผ๊ฐ ๋ด๊ธด data, ๋ทฐ ์ด๋ฆ render(map, viewName); } static void render(HashMap map, String viewName) throws IOException { String result = ""; // 1. ๋ทฐ์ ๋ด์ฉ์ ํ์ค์ฉ ์ฝ์ด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ง๋ ๋ค. Scanner sc = new Scanner(new File(viewName + ".txt")); while (sc.hasNextLine()) result += sc.nextLine() + System.lineSeparator(); // 2. map์ ๋ด๊ธด key๋ฅผ ํ๋์ฉ ์ฝ์ด์ template์ ${key}๋ฅผ value๋ฐ๊พผ๋ค. Iterator it = map.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); // 3. replace()๋ก key๋ฅผ value ์นํํ๋ค. result = result.replace("${" + key + "}", (String) map.get(key)); } // 4.๋ ๋๋ง ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. System.out.println(result); } } //[txtView1.txt] // id=${id}, pwd=${pwd} // // [txtView2.txt] // id:${id} // pwd:${pwd} // // // // [์คํ๊ฒฐ๊ณผ] // before:{} // after :{id=asdf, pwd=1111} // [txtView2.txt] // id:asdf // pwd:1111
MethodCall2.java
package com.fastcampus.ch2; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.Iterator; import java.util.Map; import java.util.Scanner; import org.springframework.ui.Model; import org.springframework.validation.support.BindingAwareModelMap; public class MethodCall2 { public static void main(String[] args) throws Exception { // 1. YoilTellerMVC์ ๊ฐ์ฒด๋ฅผ ์์ฑ Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC"); Object obj = clazz.newInstance(); // 2. main ๋ฉ์๋์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค. Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class); // 3. Model์ ์์ฑ Model model = new BindingAwareModelMap(); // Model์ ์ธํฐํ์ด์ค๋ผ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค. Model์ ๊ตฌํ์ฒด๊ฐ BindingAwareModelMap์ธ ๊ฒ์ด๋ค. System.out.println("[before] model=" + model); // 4. main ๋ฉ์๋๋ฅผ ํธ์ถ // String viewName = obj.main(2021, 10, 1, model); // ๋ฆฌํ๋ ์ API ์ฌ์ฉ X String viewName = (String) main.invoke(obj, new Object[]{2021, 10, 1, model}); // ๋ฆฌํ๋ ์ API๋ฅผ ์ด์ฉํ ํธ์ถ System.out.println("viewName=" + viewName); // Model์ ๋ด์ฉ์ ์ถ๋ ฅ System.out.println("[after] model=" + model); // ํ ์คํธ ํ์ผ์ ์ด์ฉํ rendering render(model, viewName); } // main static void render(Model model, String viewName) throws IOException { String result = ""; // 1. ๋ทฐ์ ๋ด์ฉ์ ํ์ค์ฉ ์ฝ์ด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ง๋ ๋ค. Scanner sc = new Scanner(new File("src/main/webapp/WEB-INF/views/" + viewName + ".jsp"), "utf-8"); while (sc.hasNextLine()) result += sc.nextLine() + System.lineSeparator(); // 2. model์ map์ผ๋ก ๋ณํ Map map = model.asMap(); // 3.key๋ฅผ ํ๋์ฉ ์ฝ์ด์ template์ ${key}๋ฅผ value๋ฐ๊พผ๋ค. Iterator it = map.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); // 4. replace()๋ก key๋ฅผ value ์นํํ๋ค. result = result.replace("${" + key + "}", "" + map.get(key)); } // 5.๋ ๋๋ง ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. System.out.println(result); } } /* [์คํ๊ฒฐ๊ณผ] [before] model={} viewName=yoil [after] model={year=2021, month=10, day=1, yoil=๊ธ} <%@ page contentType="text/html;charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page session="false" %> <html> <head> <title>YoilTellerMVC</title> </head> <body> <h1>2021๋ 10์ 1์ผ์ ๊ธ์์ผ์ ๋๋ค.</h1> </body> </html> */
MethodCall3.java
package com.fastcampus.ch2; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Scanner; import org.springframework.ui.Model; import org.springframework.validation.support.BindingAwareModelMap; public class MethodCall3 { public static void main(String[] args) throws Exception { // 1. ์์ฒญ ์ ๋์ด์จ ๊ฐ - request.getParameterMap(); Map map = new HashMap(); map.put("arg0", "2021"); map.put("arg1", "10"); map.put("arg2", "1"); Model model = null; Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC"); Object obj = clazz.newInstance(); // YoilTellerMVC.main(int year, int month, int day, Model model) Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class); // ํต์ฌ s Parameter[] paramArr = main.getParameters(); // main ๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก์ ๊ฐ์ ธ์จ๋ค. Object[] argArr = new Object[main.getParameterCount()]; for (int i = 0; i < paramArr.length; i++) { String paramName = paramArr[i].getName(); Class paramType = paramArr[i].getType(); Object value = map.get(paramName); // map์์ ๋ชป์ฐพ์ผ๋ฉด value๋ null // paramType์ค์ Model์ด ์์ผ๋ฉด, ์์ฑ & ์ ์ฅ if (paramType == Model.class) { argArr[i] = model = new BindingAwareModelMap(); } else if (value != null) { // map์ paramName์ด ์์ผ๋ฉด, // value์ parameter์ ํ์ ์ ๋น๊ตํด์, ๋ค๋ฅด๋ฉด ๋ณํํด์ ์ ์ฅ argArr[i] = convertTo(value, paramType); } } System.out.println("paramArr=" + Arrays.toString(paramArr)); System.out.println("argArr=" + Arrays.toString(argArr)); // ํต์ฌ e // Controller์ main()์ ํธ์ถ - YoilTellerMVC.main(int year, int month, int day, Model model) String viewName = (String) main.invoke(obj, argArr); System.out.println("viewName=" + viewName); // Model์ ๋ด์ฉ์ ์ถ๋ ฅ System.out.println("[after] model=" + model); // ํ ์คํธ ํ์ผ์ ์ด์ฉํ rendering render(model, viewName); } // main private static Object convertTo(Object value, Class type) { if (type == null || value == null || type.isInstance(value)) // ํ์ ์ด ๊ฐ์ผ๋ฉด ๊ทธ๋๋ก ๋ฐํ return value; // ํ์ ์ด ๋ค๋ฅด๋ฉด, ๋ณํํด์ ๋ฐํ if (String.class.isInstance(value) && type == int.class) { // String -> int return Integer.valueOf((String) value); } else if (String.class.isInstance(value) && type == double.class) { // String -> double return Double.valueOf((String) value); } return value; } private static void render(Model model, String viewName) throws IOException { String result = ""; // 1. ๋ทฐ์ ๋ด์ฉ์ ํ์ค์ฉ ์ฝ์ด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ง๋ ๋ค. Scanner sc = new Scanner(new File("src/main/webapp/WEB-INF/views/" + viewName + ".jsp"), "utf-8"); while (sc.hasNextLine()) result += sc.nextLine() + System.lineSeparator(); // 2. model์ map์ผ๋ก ๋ณํ Map map = model.asMap(); // 3.key๋ฅผ ํ๋์ฉ ์ฝ์ด์ template์ ${key}๋ฅผ value๋ฐ๊พผ๋ค. Iterator it = map.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); // 4. replace()๋ก key๋ฅผ value ์นํํ๋ค. result = result.replace("${" + key + "}", "" + map.get(key)); } // 5.๋ ๋๋ง ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. System.out.println(result); } } /* [์คํ๊ฒฐ๊ณผ] paramArr=[int year, int month, int day, org.springframework.ui.Model model] argArr=[2021, 10, 1, {}] viewName=yoil [after] model={year=2021, month=10, day=1, yoil=๊ธ} <%@ page contentType="text/html;charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page session="false" %> <html> <head> <title>YoilTellerMVC</title> </head> <body> <h1>2021๋ 10์ 1์ผ์ ๊ธ์์ผ์ ๋๋ค.</h1> </body> </html>
MyDispatcherServlet.java
package com.fastcampus.ch2; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.Arrays; import java.util.Iterator; import java.util.Map; import java.util.Scanner; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.ui.Model; import org.springframework.validation.support.BindingAwareModelMap; // @Controller + @RequestMapping @WebServlet("/myDispatcherServlet") // http://localhost/ch2/myDispatcherServlet?year=2021&month=10&day=1 public class MyDispatcherServlet extends HttpServlet { @Override public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { Map map = request.getParameterMap(); // year, month, day๋ฅผ map์ผ๋ก ๊ฐ์ ธ์ค๊ฒ๋๋ค. Model model = null; String viewName = ""; try { Class clazz = Class.forName("com.fastcampus.ch2.YoilTellerMVC"); Object obj = clazz.newInstance(); // 1. main๋ฉ์๋์ ์ ๋ณด๋ฅผ ์ป๋๋ค. Method main = clazz.getDeclaredMethod("main", int.class, int.class, int.class, Model.class); // 2. main๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก(paramArr)์ ์ฝ์ด์ ๋ฉ์๋ ํธ์ถ์ ์ฌ์ฉํ ์ธ์ ๋ชฉ๋ก(argArr)์ ๋ง๋ ๋ค. Parameter[] paramArr = main.getParameters(); Object[] argArr = new Object[main.getParameterCount()]; for (int i = 0; i < paramArr.length; i++) { String paramName = paramArr[i].getName(); Class paramType = paramArr[i].getType(); Object value = map.get(paramName); // paramType์ค์ Model์ด ์์ผ๋ฉด, ์์ฑ & ์ ์ฅ if (paramType == Model.class) { argArr[i] = model = new BindingAwareModelMap(); } else if (paramType == HttpServletRequest.class) { argArr[i] = request; } else if (paramType == HttpServletResponse.class) { argArr[i] = response; } else if (value != null) { // map์ paramName์ด ์์ผ๋ฉด, // value์ parameter์ ํ์ ์ ๋น๊ตํด์, ๋ค๋ฅด๋ฉด ๋ณํํด์ ์ ์ฅ String strValue = ((String[]) value)[0]; // getParameterMap()์์ ๊บผ๋ธ value๋ String๋ฐฐ์ด์ด๋ฏ๋ก ๋ณํ ํ์ argArr[i] = convertTo(strValue, paramType); } } // 3. Controller์ main()์ ํธ์ถ - YoilTellerMVC.main(int year, int month, int day, Model model) viewName = (String) main.invoke(obj, argArr); } catch (Exception e) { e.printStackTrace(); } // 4. ํ ์คํธ ํ์ผ์ ์ด์ฉํ rendering render(model, viewName, response); } // main private Object convertTo(Object value, Class type) { if (type == null || value == null || type.isInstance(value)) // ํ์ ์ด ๊ฐ์ผ๋ฉด ๊ทธ๋๋ก ๋ฐํ return value; // ํ์ ์ด ๋ค๋ฅด๋ฉด, ๋ณํํด์ ๋ฐํ if (String.class.isInstance(value) && type == int.class) { // String -> int return Integer.valueOf((String) value); } else if (String.class.isInstance(value) && type == double.class) { // String -> double return Double.valueOf((String) value); } return value; } private String getResolvedViewName(String viewName) { return getServletContext().getRealPath("/WEB-INF/views") + "/" + viewName + ".jsp"; } private void render(Model model, String viewName, HttpServletResponse response) throws IOException { String result = ""; response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); // 1. ๋ทฐ์ ๋ด์ฉ์ ํ์ค์ฉ ์ฝ์ด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ง๋ ๋ค. Scanner sc = new Scanner(new File(getResolvedViewName(viewName)), "utf-8"); while (sc.hasNextLine()) result += sc.nextLine() + System.lineSeparator(); // 2. model์ map์ผ๋ก ๋ณํ Map map = model.asMap(); // 3.key๋ฅผ ํ๋์ฉ ์ฝ์ด์ template์ ${key}๋ฅผ value๋ฐ๊พผ๋ค. Iterator it = map.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); // 4. replace()๋ก key๋ฅผ value ์นํํ๋ค. result = result.replace("${" + key + "}", map.get(key) + ""); } // 5.๋ ๋๋ง ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. out.println(result); } }
์๋ฆฌ์ ๋ํ ์์ . ๊ณ์ ๋ฐ๊ฟ๊ฐ๋ฉด์ ๋ฐ์ ์์ผ๋๊ฐ๋ฉด ์ข์ ๊ณต๋ถ๊ฐ ๋ ๊ฒ.
13~16. ์๋ธ๋ฆฟ๊ณผ JSP
1. ์๋ธ๋ฆฟ๊ณผ ์ปจํธ๋กค๋ฌ์ ๋น๊ต
์๋ธ๋ฆฟ โ ์คํ๋ง
- ์์ ์ ๊ฑฐ๋จ
- ๋งค๊ฐ๋ณ์ ํ์ํ ๊ฒ๋ง ์ ์ผ๋ฉด๋จ
- ์ ๋ํ
์ด์
๋๋ ์ ์ฒ๋ฆฌ
ใด ๊ธฐ์กด์๋ url ๋งคํ์ ํด๋์ค ๋จ์๋ก ํ์์

2. ์๋ธ๋ฆฟ์ ์๋ช ์ฃผ๊ธฐ
HelloServlet.java
package com.fastcampus.ch2; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/hello") public class HelloServlet extends HttpServlet { @Override public void init() throws ServletException { // ์๋ธ๋ฆฟ์ด ์ด๊ธฐํ๋ ๋ ์๋ ํธ์ถ๋๋ ๋ฉ์๋ // 1. ์๋ธ๋ฆฟ์ ์ด๊ธฐํ ์์ ๋ด๋น System.out.println("[HelloServlet] init() is called."); // super.init(); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. ์ ๋ ฅ // 2. ์ฒ๋ฆฌ // 3. ์ถ๋ ฅ System.out.println("[HelloServlet] service() is called."); super.service(req, resp); } @Override public void destroy() { // 3. ๋ท์ ๋ฆฌ - ์๋ธ๋ฆฟ์ด ๋ฉ๋ชจ๋ฆฌ์์ ์ ๊ฑฐ๋ ๋ ์๋ธ๋ฆฟ ์ปจํ ์ด๋์ ์ํด์ ์๋ ํธ์ถ System.out.println("[HelloServlet] destroy() is called."); super.destroy(); } }

์์ฒญ์ด ์ค๋ฉด ์๋ธ๋ฆฟ ์ธ์คํด์ค๊ฐ ์กด์ฌํ๋์ง Servlet Context์์ ํ์ธํ๋ค. ์ธ์คํด์ค๊ฐ ์กด์ฌํ๋ค๋ฉด service()๋ฅผ ํธ์ถํ๊ณ ์๋ค๋ฉด ์ธ์คํด์ค๋ฅผ ์์ฑํ๋๋ฐ, ์๋ธ๋ฆฟ์ ์ฑ๊ธํค์ผ๋ก ๋์ด์๋ค. 1๊ฐ์ ์ธ์คํด์ค๋ง ๋ง๋ค์ด์ ์ฌ์ฌ์ฉํ๋ค.
WHY? ์ฌ๋๋ง๋ค ์ฒ๋ฆฌ๋์ด์ผ ํ ์์ ์ด ๋๊ฐ์ด ๋๋ฌธ์ ํ๋ก๊ทธ๋จ์ด ์ฌ๋ฌ๊ฐ ์์ ํ์๊ฐ ์๋ค. ๊ทธ๋์ ์ฑ๊ธํค์ผ๋ก 1๊ฐ์ ์ธ์คํด์ค๋ง ๋ง๋ค์ด์ ์ฌ์ฌ์ฉํ๋ค.
+) Spring๋ ๋ง์ฐฌ๊ฐ์ง.
โ์๋ธ๋ฆฟ์ Singleton์ธ๋ฐ ์ฌ๋ฌ ์ฌ์ฉ์๊ฐ ๋์์ ๊ฐ์ ์์ฒญ์ ๋์์ ๋ณด๋ด๋ ๊ฐ๋ฅํ ์ด์ ?
์๋ธ๋ฆฟ์ด ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ๋์ํ๋๋ก ์ค๊ณ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ธ๋ฆฟ ๋ด์ iv๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค์ด์ด๋ ๊ด์ฐฎ๋ค. ์ ๋ถ ๋ค lv์ด๊ธฐ ๋๋ฌธ

iv์ฌ๋ ๊ด์ฐฎ์ ๊ฒฝ์ฐ๋
- ์์
- ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฉค๋ฒ๋ก ๊ฐ์ง๊ณ ์๋๋ฐ ์ด ๊ฐ์ฒด์ iv๊ฐ ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ
int num;
๊ณผ ๊ฐ์ iv๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋ ์ฑ๊ธํค์ผ๋ก๋ ๋ถ๊ฐ๋ฅํ๋ค.
@WebServlet("/loginTest1")
public class LoginServlet extends HttpServlet {
LoginFilter loginFilter; // iv, loginFilter๋ iv๊ฐ ์์.
final int MAX_VALUE = 10; // iv์ง๋ง ์์๋ผ์ OK
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String pwd = request.getParameter("pwd");
}
}
๊ทธ๋์ ์คํ๋ง์์๋ 2๊ฐ์ง๋ฅผ ์ ๊ณตํ๋ค.
- Singleton : default, 1๊ฐ
- Prototype : ์์ฒญํ ๋๋ง๋ค ๊ฐ์ฒด ์์ฑ. iv ์ฌ์ฉ ๊ฐ๋ฅ
Prototype์ผ๋ก ์ฌ์ฉํ ๊ฒฝ์ฐ ์๋ฒ ๋ถ๋ด์ด ํฌ๊ธฐ ๋๋ฌธ์ ์ฌ๋งํ๋ฉด iv๋ ์ฌ์ฉํ์ง ์๋ ๊ฒ ์ข๋ค.(์์์ ์ค๋ช ํ ๊ฒฝ์ฐ๋ ์ ์ธ(1. ์์, 2. ํฌํจ ๊ด๊ณ์ธ๋ฐ ๊ทธ ๊ฐ์ฒด์ iv๊ฐ ์๋ ๊ฒฝ์ฐ)
Servlet Context : ์๋ธ๋ฆฟ ์ปจํ ์คํธ์ ํฌํจ๋ ์๋ธ๋ฆฟ๋ค์ด ์ฌ๊ธฐ ๋ค ๋ฑ๋ก๋์ด์๋ค.

4. JSP์ ์๋ธ๋ฆฟ์ ๋น๊ต

5. JSP์ ํธ์ถ ๊ณผ์

6. JSP์ ์๋ธ๋ฆฟ์ผ๋ก ๋ณํ๋ JSP ๋น๊ต

7. JSP์ ๊ธฐ๋ณธ ๊ฐ์ฒด

๊ธฐ๋ณธ ๊ฐ์ฒด | ํ์ | ์ค๋ช |
---|---|---|
request | javax.servlet.http.HttpServletRequest | ์์ฒญ ์ ๋ณด๊ฐ ๋ด๊ฒจ์๋ ๊ฐ์ฒด |
response | javax.servlet.http.HttpServletResponse | ์์ฒญ์ ์๋ต์ ์์ฑํ ๋ ์ฌ์ฉ |
session | javax.servlet.http.HttpSession | HTTP session์ ๊ตฌํํ ๊ฐ์ฒด. ์ธ์ ์ ๋ณด ์ ์ฅ์ ์ฌ์ฉ |
application | javax.servlet.ServletContext | Web Application ์ ์ฒด์์ ๊ณต์ ํ๋ ๊ฐ์ฒด |
config | javax.servlet.ServletConfig | JSP ํ์ด์ง์ ๋ํ ์ค์ ์ ๋ณด๊ฐ ๋ด๊ธด ๊ฐ์ฒด |
page | java.lang.Object | JSP ํ์ด์ง ๊ฐ์ฒด ์์ |
pageContext | javax.servlet.jsp.PageContext | JSPํ์ด์ง์ context์ ๋ณด๋ฅผ ์ ๊ณต |
out | javax.servlet.jsp.JspWriter | ์๋ต์ ํฌํจ๋ ๋ด์ฉ์ ์ถ๋ ฅํ ๋ ์ฌ์ฉ |
exception | java.lang.Throwable | ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์์ฑ๋๋ ์์ธ ๊ฐ์ฒด |
8. ์ ํจ ๋ฒ์(scope)์ ์์ฑ(attribute)
<4๊ฐ ์ ์ฅ์>
- ์ ๊ทผ ๋ฒ์
- ์์กด ๊ธฐ๊ฐ
1. pageContext

2. application

3. session

4. request

requestInfo.java
package com.fastcampus.Test; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; @Controller public class RequestInfo { @RequestMapping("/requestInfo") // public static void main(String[] args) { public void main(HttpServletRequest request) { System.out.println("request.getCharacterEncoding()="+request.getCharacterEncoding()); // ์์ฒญ ๋ด์ฉ์ ์ธ์ฝ๋ฉ System.out.println("request.getContentLength()="+request.getContentLength()); // ์์ฒญ ๋ด์ฉ์ ๊ธธ์ด. ์์ ์์ ๋๋ -1 System.out.println("request.getContentType()="+request.getContentType()); // ์์ฒญ ๋ด์ฉ์ ํ์ . ์ ์ ์์ ๋๋ null System.out.println("request.getMethod()="+request.getMethod()); // ์์ฒญ ๋ฐฉ๋ฒ System.out.println("request.getProtocol()="+request.getProtocol()); // ํ๋กํ ์ฝ์ ์ข ๋ฅ์ ๋ฒ์ ผ HTTP/1.1 System.out.println("request.getScheme()="+request.getScheme()); // ํ๋กํ ์ฝ System.out.println("request.getServerName()="+request.getServerName()); // ์๋ฒ ์ด๋ฆ ๋๋ ip์ฃผ์ System.out.println("request.getServerPort()="+request.getServerPort()); // ์๋ฒ ํฌํธ System.out.println("request.getRequestURL()="+request.getRequestURL()); // ์์ฒญ URL System.out.println("request.getRequestURI()="+request.getRequestURI()); // ์์ฒญ URI System.out.println("request.getContextPath()="+request.getContextPath()); // context path System.out.println("request.getServletPath()="+request.getServletPath()); // servlet path System.out.println("request.getQueryString()="+request.getQueryString()); // ์ฟผ๋ฆฌ ์คํธ๋ง System.out.println("request.getLocalName()="+request.getLocalName()); // ๋ก์ปฌ ์ด๋ฆ System.out.println("request.getLocalPort()="+request.getLocalPort()); // ๋ก์ปฌ ํฌํธ System.out.println("request.getRemoteAddr()="+request.getRemoteAddr()); // ์๊ฒฉ ip์ฃผ์ System.out.println("request.getRemoteHost()="+request.getRemoteHost()); // ์๊ฒฉ ํธ์คํธ ๋๋ ip์ฃผ์ System.out.println("request.getRemotePort()="+request.getRemotePort()); // ์๊ฒฉ ํฌํธ } } // //[์คํ๊ฒฐ๊ณผ] http://localhost:8080/ch2/requestInfo?year=2021&month=10&day=1 //request.getCharacterEncoding()=UTF-8 //request.getContentLength()=-1 //request.getContentType()=null //request.getMethod()=GET //request.getProtocol()=HTTP/1.1 //request.getScheme()=http //request.getServerName()=localhost //request.getServerPort()=8080 //request.getRequestURI()=http://localhost:8080/ch2/requestInfo //request.getRequestURI()=/ch2/requestInfo //request.getContextPath()=/ch2 //request.getServletPath()=/requestInfo //request.getQueryString()=year=2021&month=10&day=1 //request.getLocalName()=localhost //request.getLocalPort()=8080 //request.getRemoteAddr()=0:0:0:0:0:0:0:1 <--- AWS์ ๋ฐฐํฌ(deploy)ํ ๋ค์์ ์คํํ๋ฉด, ์ค์ ip์ฃผ์๋ฅผ ํ์ธํ ์ ์์. //request.getRemoteHost()=0:0:0:0:0:0:0:1 <--- AWS์ ๋ฐฐํฌ(deploy)ํ ๋ค์์ ์คํํ๋ฉด, ์ค์ ip์ฃผ์๋ฅผ ํ์ธํ ์ ์์. //request.getRemotePort()=54855
๋ฉ์๋ | ์ค๋ช |
---|---|
String getRemoteAddr() | ์์ฒญํ ์ปดํจํฐ์ IP์ฃผ์๋ฅผ ๋ฐํ. |
long getContentLength() | ์์ฒญ์ ์ ์กํ ๋ฐ์ดํฐ์ ๊ธธ์ด๋ฅผ ๋ฐํ. ๊ธธ์ด๋ฅผ ์์ ์์ ๋๋ -1์ ๋ฐํ |
String getCharacterEncoding() | ์์ฒญ์ ํฌํจ๋ ๋ชจ๋ ํ๋ผ๋ฏธํฐ์ ์ด๋ฆ์ Enumeration์ ๋ด์์ ๋ฐํ |
String getContentType() | ์์ฒญ์ ํฌํจ๋ ๋ชจ๋ ํ๋ผ๋ฏธํฐ์ ์ด๋ฆ๊ณผ ๊ฐ์ Map์ ๋ด์ ๋ฐํ |
String getProtocol() | ์์ฒญํ ํด๋ผ์ด์ธํธ์ ํ๋กํ ์ฝ๊ณผ ๋ฒ์ ์ ๋ฐํ(HTTP/1.1) |
String getMethod() | ์์ฒญ ๋ฐฉ์(GET, POST ๋ฑ) |
String getRequestURL() | ์์ฒญํ URL์ ๋ฐํ(URL์ ์ฒด๋ฅผ ๋ฐํ) โ |
String getRequestURI() | ์์ฒญํ URI๋ฅผ ๋ฐํ(URL์์ ์ฌ์ดํธ ์ฃผ์๋ฅผ ๋บ ๋๋จธ์ง) |
String getContextPath() | ์์ฒญํ URI๊ฐ ์ํ context path๋ฅผ ๋ฐํ |
String getServletPath() | ์์ฒญํ URI์์ context path๋ฅผ ์ ์ธํ ๋๋จธ์ง |
String getQueryString() | ์์ฒญ์ ํฌํจ๋ ์ฟผ๋ฆฌ ์คํธ๋ง(query string)์ ๋ฐํ |
String getServerName() | ์์ฒญ์ ๋ฐ์ ์๋ฒ์ ์ด๋ฆ์ ๋ฐํ |
int getServerPort() | ์์ณฅ์ ๋ฐ์ ์๋ฒ๊ฐ ์ฌ์ฉํ ํฌํธ๋ฅผ ๋ฐํ |
a.jsp โ b.jsp
refer โ requestURI
์ด๋ค ์ฌ์ดํธ๋ฅผ ํตํด ์๋์ง ์ ์ ์๋ค.
5. page, request, session, application ์ ๋ฆฌ

๊ธฐ๋ณธ ๊ฐ์ฒด | ์ ํจ ๋ฒ์ | ์ค๋ช |
---|---|---|
pageContext | 1๊ฐ JSPํ์ด์ง | JSPํ์ด์ง์ ์์๋ถํฐ ๋๊น์ง. ํด๋น JSP ๋ด๋ถ์์๋ง ์ ๊ทผ๊ฐ๋ฅ. ํ์ด์ง๋น 1๊ฐ |
request | 1+๊ฐ JSPํ์ด์ง | ์์ฒญ์ ์์๋ถํฐ ์๋ต๊น์ง. ๋ค๋ฅธ JSP๋ก ์ ๋ฌ ๊ฐ๋ฅ. ์์ฒญ๋ง๋ค 1๊ฐ |
session | n๊ฐ JSPํ์ด์ง | session์ ์์๋ถํฐ ์ข ๋ฃ๊น์ง(๋ก๊ทธ์ธ ~ ๋ก๊ทธ์์). ํด๋ผ์ด์ธํธ๋ง๋ค 1๊ฐ |
application | context ์ ์ฒด | Web Application์ ์์๋ถํฐ ์ข
๋ฃ๊น์ง. context๋ด๋ถ ์ด๋์๋ ์ ๊ทผ ๊ฐ๋ฅ ๋ชจ๋ ํด๋ผ์ด์ธํธ๊ฐ ๊ณต์ . context๋ง๋ค 1๊ฐ |
์์ฑ ๊ด๋ จ ๋ฉ์๋ | ์ค๋ช |
---|---|
void setAttribute(String name, Object value) | ์ง์ ๋ ๊ฐ(value)์ ์ง์ ๋ ์์ฑ ์ด๋ฆ(name)์ผ๋ก ์ ์ฅ |
Object getAttribute(String name) | ์ง์ ๋ ์ด๋ฆ(name)์ผ๋ก ์ ์ฅ๋ ์์ฑ์ ๊ฐ์ ๋ฐํ |
void removeAttribute(String name) | ์ง์ ๋ ์ด๋ฆ(name)์ ์์ฑ์ ์ญ์ |
Enumeration getAttributeNames() | ๊ธฐ๋ณธ ๊ฐ์ฒด์ ์ ์ฅ๋ ๋ชจ๋ ์์ฑ์ ์ด๋ฆ์ ๋ฐํ |
9. URL ํจํด
@WebServlet์ผ๋ก ์๋ธ๋ฆฟ์ URL์ ๋งคํํ ๋ ์ฌ์ฉ
์ข
๋ฅ | URL pattern | ๋งค์นญ URL |
---|---|---|
1. exact mapping (์ ํํ ์ผ์น) | /login/hello.do | http://localhost/ch2/login/hello.do |
2. path mapping (๊ฒฝ๋ก) | /login/* | http://localhost/ch2/login/ http://localhost/ch2/login/hello http://localhost/ch2/login/hello.do http://localhost/ch2/login/test/ |
3. extension mapping (ํ์ฅ์) | *.do, *.jsp | http://localhost/ch2/hi.do http://localhost/ch2/login/hello.do |
4. default mapping (๋ํดํธ) | / | http://localhost/ch2/ http://localhost/ch2/hello.do http://localhost/ch2/login/ http://localhost/ch2/login/hello http://localhost/ch2/login/hello.do |
+) ๋ํดํธ ์์ : DispatcherServlet, ์ธ์ฝ๋ฉ ํํฐ
loadOnStartup
= ๋ฏธ๋ฆฌ ๊ฐ์ฒด ๋ง๋ค์ด๋๋ ์ต์
์๋ธ๋ฆฟ์ ์ฒซ ์์ฒญ ์ ๊ฐ์ฒด ์์ฑ(Lazy-init)5
// @WebServlet(urlPatterns = {"/hello", "/hello/*"}, loadOnStartup = 1)
@WebServlet("/hello")
public class HelloServlet extends HttpServlet { }



์๋๋ default ์๋ธ๋ฆฟ์ด ๋ฐ๋๋ก ๋์ด์๋๋ฐ, ๊ฐ๋ณ ์ค์ ์์ DispatcherServelt์ด ๋ชจ๋ ์์ฒญ์ ๋ฐ๋๋ก ๋ฎ์ด์์์ ธ์๋ค.
10. EL(Expression Language)
request ๊ฐ์ฒด์ ์ ์ฅ์ ํด์ผ์ง๋ง EL๋ก ์ฝ์ ์ ์๋ค.

11. JSTL(JSP Standard Tag library)

2. Filter
๋์ค๊ฒ๋ ๋ฐฐ๊ฒฝ : ์ฝ๋ ๋ถ๋ฆฌ, ์ค๋ณต ์ ๊ฑฐ
<์์>
CharacterEncodingFilter
โ ํ๊ธ ์ฒ๋ฆฌ๋ฅผ ํด์ค๋ค.(์์ฒญ๊ณผ ์๋ต์ ๋ ๋ฒ)
์๋๋ request.setCharacterEncoding(โUTF-8โ); ์ง์ ํด์ค์ผ ํจ
response๋ ๋ง์ฐฌ๊ฐ์ง. ์ด ์ฝ๋๋ฅผ ์๋ธ๋ฆฟ์์ Filter๋ก ์ฎ๊ธด ๊ฒ
- ๋ก๊น
์ด๋ค ์์ฒญ์ด ๋ค์ด์๋์ง ๋ค ๋ณผ ์ ์๋ค. โ ์ฌ์ฉ์๊ฐ ์ด๋ค ํ์ด์ง์์ ๊ฐ์ฅ ์ค๋ ๋จธ๋ฌผ๋ ๋์ง ํต๊ณ๋ด๊ธฐ ๊ฐ๋ฅ
Filter1 - 1. ์ ์ฒ๋ฆฌ
Filter2 - 1. ์ ์ฒ๋ฆฌ
์๋ธ๋ฆฟ - ์ฒ๋ฆฌ
Filter2 - 3. ํ์ฒ๋ฆฌ
Filter2 - 3. ํ์ฒ๋ฆฌ



17~18. @RequestParam๊ณผ @ModelAttribute / RequestMapping
1. @RequestParam
- ์์ฒญ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฐ๊ฒฐํ ๋งค๊ฐ๋ณ์์ ๋ถ์ด๋ ์ ๋ํ ์ด์ , ์๋ต๊ฐ๋ฅ
<์์ >
RequestParamTest.java
package com.fastcampus.ch2; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class RequestParamTest { // ExceptionHandler ์ ๋ํ ์ด์ ์ด ๋ถ์ผ๋ฉด, ๊ดํธ์์ ์์ธ ๋ฐ์ ์ ์ด ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค. @ExceptionHandler(Exception.class) public String catcher(Exception ex) { return "yoilError"; } @RequestMapping("/requestParam") public String main(HttpServletRequest request) { String year = request.getParameter("year"); // http://localhost/ch2/requestParam ---->> year=null // http://localhost/ch2/requestParam?year= ---->> year="" // http://localhost/ch2/requestParam?year ---->> year="" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam2") // public String main2(@RequestParam(name="year", required=false) String year) { // ์๋์ ๋์ผ public String main2(String year) { // http://localhost/ch2/requestParam2 ---->> year=null // http://localhost/ch2/requestParam2?year ---->> year="" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam3") // public String main3(@RequestParam(name="year", required=true) String year) { // ์๋์ ๋์ผ public String main3(@RequestParam String year) { // http://localhost/ch2/requestParam3 ---->> year=null 400 Bad Request. required=true๋ผ์ // http://localhost/ch2/requestParam3?year ---->> year="" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam4") public String main4(@RequestParam(required = false) String year) { // http://localhost/ch2/requestParam4 ---->> year=null // http://localhost/ch2/requestParam4?year ---->> year="" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam5") public String main5(@RequestParam(required = false, defaultValue = "1") String year) { // http://localhost/ch2/requestParam5 ---->> year=1 // http://localhost/ch2/requestParam5?year ---->> year=1 System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } // ======================================================================= @RequestMapping("/requestParam6") public String main6(int year) { // http://localhost/ch2/requestParam6 ---->> 500 java.lang.IllegalStateException: Optional int parameter 'year' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type. // http://localhost/ch2/requestParam6?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: "" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam7") public String main7(@RequestParam int year) { // http://localhost/ch2/requestParam7 ---->> 400 Bad Request, Required int parameter 'year' is not present // http://localhost/ch2/requestParam7?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: "" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam8") public String main8(@RequestParam(required = false, defaultValue = "2021") int year) { // ํ์๊ฐ ์๋ ๊ทธ๋์ ์๋ฒ ์ค๋ฅ ํ์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ด ๊ฐ์ด ์ ๋ค์ด์์ ๋์ ๋๋น๊ฐ ๋์ด์์ด์ผ ํ๋ค. // http://localhost/ch2/requestParam8 ---->> 500 java.lang.IllegalStateException: Optional int parameter 'year' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type. // http://localhost/ch2/requestParam8?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: "" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam9") public String main9(@RequestParam(required = true) int year) { // http://localhost/ch2/requestParam9 ---->> 400 Bad Request, Required int parameter 'year' is not present // http://localhost/ch2/requestParam9?year ---->> 400 Bad Request, nested exception is java.lang.NumberFormatException: For input string: "" System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam10") public String main10(@RequestParam(required = true, defaultValue = "1") int year) { // http://localhost/ch2/requestParam10 ---->> year=1 // http://localhost/ch2/requestParam10?year ---->> year=1 System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } @RequestMapping("/requestParam11") public String main11(@RequestParam(required = false, defaultValue = "1") int year) { // http://localhost/ch2/requestParam11 ---->> year=1 // http://localhost/ch2/requestParam11?year ---->> year=1 System.out.printf("[%s]year=[%s]%n", new Date(), year); return "yoil"; } } // class
- ์ ๋ํ
์ด์
์ ๋ถ์ด๋ฉด ํ์๊ฐ ์๋
http://localhost/requestParam2 โ year=null
http://localhost/requestParam?year โ year=โโ
@RequestMapping("/requestParam2") // public String main2(@RequestParam(name = "year", required = false) String year) { ์๋์ ๋์ผ public String main2(String year) { ... // ์ ๋ํ ์ด์ ์ ๋ถ์ด๋ฉด ํ์๊ฐ ์๋ }
- ์ ๋ํ
์ด์
๋ถ์ด๋ฉด ํ์๊ฐ
http://localhost/requestParam3 โ year=null // 400 Bad Request. required=true๋ผ์
โ ํด๋ผ์ด์ธํธ ์๋ชป. ์์ฒญํ ์ฌ๋์ด ์ค์ผ ํ ๊ฐ์ ์์ค
http://localhost/requestParam3?year โ year=โโ
@RequestMapping("/requestParam3") // public String main3(@RequestParam(name = "year", required = true) String year) { // ์๋์ ๋์ผ public String main3(@RequestParam String year) { // ์ ๋ํ ์ด์ ๋ถ์ด๋ฉด ํ์๊ฐ }
YoilTellerMVC2.java
package com.fastcampus.Test; import java.util.Calendar; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class YoilTellerMVC2 { @ExceptionHandler(Exception.class) public String catcher(Exception ex) { return "yoilError"; } @RequestMapping("/getYoilMVC2") // http://localhost/ch2/getYoilMVC2 public String main(@RequestParam(required = true) int year, @RequestParam(required = true) int month, @RequestParam(required = true) int day, Model model) { // 1. ์ ํจ์ฑ ๊ฒ์ฌ if (!isValid(year, month, day)) return "yoilError"; // ์ ํจํ์ง ์์ผ๋ฉด, /WEB-INF/views/yoilError.jsp๋ก ์ด๋ // 2. ์ฒ๋ฆฌ char yoil = getYoil(year, month, day); // 3. Model์ ์์ ๊ฒฐ๊ณผ ์ ์ฅ model.addAttribute("year", year); model.addAttribute("month", month); model.addAttribute("day", day); model.addAttribute("yoil", yoil); // 4. ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค View์ ์ด๋ฆ์ ๋ฐํ return "yoil"; // /WEB-INF/views/yoil.jsp } private char getYoil(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.set(year, month - 1, day); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek); } private boolean isValid(int year, int month, int day) { if (year == -1 || month == -1 || day == -1) return false; return (1 <= month && month <= 12) && (1 <= day && day <= 31); // ๊ฐ๋จํ ์ฒดํฌ } }
์์ธ์ฒ๋ฆฌ
ํ์ ์ ๋ ฅ O โ ์์ธ์ฒ๋ฆฌ
ํ์ ์ ๋ ฅ X โ ๊ธฐ๋ณธ๊ฐ์ ์ค์ผ ํ๋ค.
// ExceptionHandler ์ ๋ํ
์ด์
์ด ๋ถ์ผ๋ฉด, ๊ดํธ์์ ์์ธ ๋ฐ์ ์ ์ด ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
@ExceptionHandler(Exception.class)
public String catcher(Exception ex) {
return "yoilError";
}
๋ก๊ทธ ๋ ๋ฒจ ์ค์ trace๊ฐ ๊ฐ์ฅ ์์ธํ ๋ ๋ฒจ์ด๋ค.
<logger name="org.springframework.web">
<level value="trace" />
</logger>
info -> trace ๋ณ๊ฒฝ

์ด์ ๋ ์์ YoilTellerMVC2
์์ year, month, day๋ฅผ ํ๋๋ก ํฉ์ณ๋ณด์
์ ๋ ฅ๋ฐ๋ ๊ฐ๋ค์ด ๋ง์ ๋๋ ๋งค๊ฐ๋ณ์์ ๊ฐ์๋ฅผ ์ค์ด๊ธฐ ์ํด์ ํด๋์ค๋ฅผ ํ๋ ์ ์ํด๋๊ณ ์ด ๋งค๊ฐ๋ณ์๋ก ํ๋๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
์ฅ์ : ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ๊ฐ๋ค์ด ์ค์ด๋ค๊ฑฐ๋ ๋ง์์ ธ๋ ์ฝ๋ ๋ฐ๊ฟ ํ์ X MyDate๋ง ๋ณ๊ฒฝํ๋ฉด๋จ. ๋ณ๊ฒฝ์ ์ ๋ฆฌํ ์ฝ๋๊ฐ ๋๋ค.
public String main(int year, int month, int day, Model model) // ๊ธฐ์กด
public String main(MyDate date, Model model) // ๋ณ๊ฒฝ
YoilTellerMVC4.java
(year, month, day๋ฅผ myDate ํด๋์ค๋ก ํฉ์น ์์ )package com.fastcampus.ch2; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Calendar; @Controller public class YoilTellerMVC4 { @ExceptionHandler(Exception.class) public String catcher(Exception ex) { return "yoilError"; } // ๋ง์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ด์ฃผ์ด์ผ ํ ๋๋ ์๋ก์ด ํด๋์ค๋ฅผ ์ ์ํด์ ๋งค๊ฐ๋ณ์์ ๊ฐ์๋ฅผ ์ค์ผ ์ ์๋ค. @RequestMapping("/getYoilMVC4") // http://localhost/ch2/getYoilMVC2 public String main(MyDate date, Model model) { // 1. ์ ํจ์ฑ ๊ฒ์ฌ if (!isValid(date)) return "yoilError"; // ์ ํจํ์ง ์์ผ๋ฉด, /WEB-INF/views/yoilError.jsp๋ก ์ด๋ // 2. ์ฒ๋ฆฌ char yoil = getYoil(date); // 3. Model์ ์์ ๊ฒฐ๊ณผ ์ ์ฅ model.addAttribute("myDate", date); model.addAttribute("yoil", yoil); // 4. ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค View์ ์ด๋ฆ์ ๋ฐํ return "yoil"; // /WEB-INF/views/yoil.jsp } private boolean isValid(MyDate date) { return isValid(date.getYear(), date.getMonth(), date.getDay()); } private char getYoil(MyDate date) { return getYoil(date.getYear(), date.getMonth(), date.getDay()); } private char getYoil(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.set(year, month - 1, day); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek); } private boolean isValid(int year, int month, int day) { if (year == -1 || month == -1 || day == -1) return false; return (1 <= month && month <= 12) && (1 <= day && day <= 31); // ๊ฐ๋จํ ์ฒดํฌ } }
โ์ ๋ ฅ๋๋ ๊ฐ์ด year, month, day์ธ๋ฐ ์ ํ ๊ด๊ณ ์๋ ํ์ ์ MyDate๋ฅผ ์ ์ธํด๋ ์ด๊ฑธ ๋ค ์์์ ๋ฃ์ด์ค๋ค๊ณ ?
์๋์ ์์ ๋ฅผ ๋ณด๋ฉด ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋๋์ง ์ ์ ์๋ค.
SetterCall.java
package com.fastcampus.ch2; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.springframework.util.StringUtils; public class SetterCall { public static void main(String[] args) throws Exception{ Map<String, String> map = new HashMap<>(); map.put("year", "2021"); map.put("month", "10"); map.put("day", "1"); Class<?> type = Class.forName("com.fastcampus.ch2.MyDate"); // MyDate์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , map์ ๊ฐ์ผ๋ก ์ด๊ธฐํํ๋ค. Object obj = dataBind(map, type); System.out.println("obj="+obj); // obj=[year=2021, month=10, day=1] } // main private static Object dataBind(Map<String, String> map, Class<?> clazz) throws Exception { // 1. MyDate์ธ์คํด์ค ์์ฑ // Object obj = clazz.newInstance(); // deprecated method Object obj = clazz.getDeclaredConstructor().newInstance(new Object[0]); // 2. MyDate์ธ์คํด์ค์ setter๋ฅผ ํธ์ถํด์, map์ ๊ฐ์ผ๋ก MyDate๋ฅผ ์ด๊ธฐํ // 2-1. MyDate์ ๋ชจ๋ iv๋ฅผ ๋๋ฉด์ map์ ์๋์ง ์ฐพ๋๋ค. // 2-2. ์ฐพ์ผ๋ฉด, ์ฐพ์ ๊ฐ์ setter๋ก ๊ฐ์ฒด์ ์ ์ฅํ๋ค. Field[] ivArr = clazz.getDeclaredFields(); for(int i=0;i<ivArr.length;i++) { String name = ivArr[i].getName(); Class<?> type = ivArr[i].getType(); // map์ ๊ฐ์ ์ด๋ฆ์ key๊ฐ ์์ผ๋ฉด ๊ฐ์ ธ์์ setterํธ์ถ Object value = map.get(name); // ๋ชป์ฐพ์ผ๋ฉด value์ ๊ฐ์ null Method method = null; try { // map์ iv์ ์ผ์นํ๋ ํค๊ฐ ์์ ๋๋ง, setter๋ฅผ ํธ์ถ if(value==null) continue; method = clazz.getDeclaredMethod(getSetterName(name), type); // setter์ ์ ๋ณด ์ป๊ธฐ System.out.println("method="+method); method.invoke(obj, convertTo(value, type)); // obj์ setter๋ฅผ ํธ์ถ } catch(Exception e) { e.printStackTrace(); } } System.out.println(Arrays.toString(ivArr)); return obj; } private static Object convertTo(Object value, Class<?> type) { // value์ ํ์ ๊ณผ type์ ํ์ ์ด ๊ฐ์ผ๋ฉด ๊ทธ๋๋ก ๋ฐํ if(value==null || type==null || type.isInstance(value)) return value; // value์ ํ์ ๊ณผ type์ด ๋ค๋ฅด๋ฉด, ๋ณํํด์ ๋ฐํ if(String.class.isInstance(value) && type==int.class) // String -> int return Integer.valueOf(""+value); return value; } // iv์ ์ด๋ฆ์ผ๋ก setter์ ์ด๋ฆ์ ๋ง๋ค์ด์ ๋ฐํํ๋ ๋ฉ์๋("day" -> "setDay") private static String getSetterName(String name) { // return "set"+name.substring(0,1).toUpperCase()+name.substring(1); return "set" + StringUtils.capitalize(name); // org.springframework.util.StringUtils } } /* [์คํ๊ฒฐ๊ณผ] method=public void com.fastcampus.ch2.MyDate.setYear(int) method=public void com.fastcampus.ch2.MyDate.setMonth(int) method=public void com.fastcampus.ch2.MyDate.setDay(int) [private int com.fastcampus.ch2.MyDate.year, private int com.fastcampus.ch2.MyDate.month, private int com.fastcampus.ch2.MyDate.day] obj=[year=2021, month=10, day=1] */
- ์์ฒญํ ๊ฐ๋ค์ด HashMap์ผ๋ก ๋ค์ด์จ๋ค.(๋ด๊ธด๋ค.)
- MyDate๋ผ๋ ํ์
์ด ์์ ๋ bind()๋ฉ์๋๊ฐ Mapํ๊ณ ์ฐ๊ฒฐํด์ค๋ค.
1) ํ์ ์ผ๋ก ๋์ด์จ ํด๋์ค ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
2) MyDate ์ธ์คํด์ค์ setter๋ฅผ ํธ์ถํด์, Map์ ๊ฐ์ผ๋ก MyDate๋ฅผ ์ด๊ธฐํํ๋ค.
2-1. myDate์ ๋ชจ๋ iv๋ฅผ ๋๋ฉด์ Map์ ์กด์ฌํ๋์ง ์ฐพ๋๋ค.
2-2. ์ฐพ์ผ๋ฉด, ์ฐพ์ ๊ฐ์ setter๋ก ๊ฐ์ฒด์ ์ ์ฅํ๋ค.
โ setter๊ฐ ์์ผ๋ฉด ์คํ๋ง์ด ์๋์ผ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ๋ชปํจ. setter ํ์.
2. @ModelAttribute
- ์ ์ฉ ๋์์ Model์ ์์ฑ์ผ๋ก ์๋ ์ถ๊ฐํด์ฃผ๋ ์ ๋ํ ์ด์
- ๋ฐํ ํ์ or Controller ๋ฉ์๋์ ๋งค๊ฐ๋ณ์์ ์ ์ฉ ๊ฐ๋ฅ
//public String main(@ModelAttribute("myDate") MyDate date, Model m) { // ์๋์ ๋์ผ
public String main(@ModelAttribute MyDate date, Model m) { // ์ฐธ์กฐํ ๋งค๊ฐ๋ณ์์ธ ๊ฒฝ์ฐ์ @ModelAttribute ์๋ต ๊ฐ๋ฅ
//public String main(MyDate date, Model m) {
char yoil = getYoil(data);
// 3. Model์ ์์
ํ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅ
m.addAttribute("myDate", date); //
m.addAttribute("yoil", yoil);
// 4. ์์
๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค ๋ทฐ์ ์ด๋ฆ์ ๋ฐํ
return "yoil";
}
private @ModelAttribute("yoil") char getYoil(MyDate date) { // ๋ฉ์๋๊ฐ ์๋์ผ๋ก ํธ์ถ๋๊ณ ์ด ๊ฒฐ๊ณผ๊ฐ model์ ์ ์ฅ๋๋ค.
return getYoil(date.getYear(), date.getMonth(), date.getDay());
}
์ปจํธ๋กค๋ฌ์ ๋งค๊ฐ๋ณ์์ ๋ถ์ด๋ ์ ๋ํ ์ด์
@RequestParam
: ๊ธฐ๋ณธํ, String(์๋ต ๊ฐ๋ฅ)์ฐธ์กฐํ ๋งค๊ฐ๋ณ์์ ๊ฒฝ์ฐ์๋ ์ด ์ ๋ํ ์ด์ ๋ชป ๋ถ์. ์ฌ๋ฌ ๊ฐ์ด ๋ฐ์ธ๋ฉ๋๊ธฐ ๋๋ฌธ.
๊ธฐ๋ณธํ์ด๋ String ๊ฐ์ ๊ฒฝ์ฐ ๊ตณ์ด ๋ชจ๋ธ์ ์ ์ฅํ ํ์X ๋ทฐ์์ ${param.ํ๋ผ๋ฏธํฐ์ด๋ฆ}์ผ๋ก ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
@ModelAttribute
: ์ฐธ์กฐํ(์๋ต ๊ฐ๋ฅ, ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ์ด์๋ค๊ณ ๋ณด๋ฉด๋จ)
3. WebDataBinder
: ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด์ ์์ฒญ๋ฐ์ ๊ฐ์ด ์ค์ ๊ฐ์ฒด์ Binding๋ ๋ ์ค๊ฐ ์ญํ ์ ํด์ฃผ๋ ๊ฒ
String์ผ๋ก ๋์ด์จ ๊ฑธ ๋ณํํด์ฃผ๊ณ ๊ฒ์ฆํด์ฃผ๋ ์
์ญํ
- ํ์ ๋ณํ
- ๋ฐ์ดํฐ ๊ฒ์ฆ
- ๊ฒฐ๊ณผ(BindingResult์ ์ ์ฅ)
- Controller์ ๋๊ฒจ์ค๋ค.

๋ณดํต์ ์ปจํธ๋กค๋ฌ ๋ฉ์๋๊ฐ ๋ฐ์ ์ ์๋๋ฐ ์ง๊ธ์ ๋ธ๋ผ์ฐ์ ์์ ์ง์ url์ ์น๊ณ ํ๋ฒ์ ๋ค์ด์๊ธฐ ๋๋ฌธ์ ์ปจํธ๋กค๋ฌ๊น์ง ๋ชป๊ฐ๊ณ ๊ทธ ์์์ ์๋ฌ๊ฐ ๋ฐ์ํด ํธ๋ค๋ฌ๋ก ์ฒ๋ฆฌ๋ฅผ ํ ๊ฒ. ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ ์๋.
์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ form์ผ๋ก ๋ฐ๋ ๊ฒฝ์ฐ๊ณ . ๊ทธ๋ด ๋๋ ์ปจํธ๋กค๋ฌ์ BindingResult๋ก ๊ฐ์ด ๋ค ๋์ด์ฌ ์ ์๋ค. ์๋ ์์ ๋ ์์ธ์ ์ธ ๊ฒฝ์ฐ
์๋ฌ๊ฐ ๋ฐ์ํด๋ result๋ก Controller์์๋ ๊ฒฐ๊ณผ ๋ณด๊ธฐ ๊ฐ๋ฅ
YoilTellerMVC6.java
package com.fastcampus.ch2; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Calendar; @Controller public class YoilTellerMVC6 { @ExceptionHandler(Exception.class) public String catcher(Exception ex, BindingResult result) { // BindingResult๊ฐ ์๋ฌ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ์๋ฌ ๊ฐ์ฒด๋ก๋ถํฐ ์ด๋ค ๊ฐ๋ค์ ์ป์ ์ ์๋์ง ๋ณด๋ ค๊ณ ํใ กใด ๊ฒ System.out.println("result = " + result); FieldError error = result.getFieldError(); System.out.println("error.getCode() = " + error.getCode()); System.out.println("error.getField() = " + error.getField()); System.out.println("error.getDefaultMessage() = " + error.getDefaultMessage()); ex.printStackTrace(); return "yoilError"; } // ๋ง์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ์ด์ฃผ์ด์ผ ํ ๋๋ ์๋ก์ด ํด๋์ค๋ฅผ ์ ์ํด์ ๋งค๊ฐ๋ณ์์ ๊ฐ์๋ฅผ ์ค์ผ ์ ์๋ค. @RequestMapping("/getYoilMVC6") // http://localhost/ch2/getYoilMVC5 // public String main(@ModelAttribute("myDate") MyDate date, Model model) { // ์๋์ ๋์ผ public String main(MyDate date, BindingResult result) { // key ์๋ต ์ ํ์ ์ ์ฒซ ๊ธ์๋ฅผ ์๋ฌธ์๋ก ํ ๊ฑธ key๋ก ์ฌ์ฉ. System.out.println("result" + result); // 1. ์ ํจ์ฑ ๊ฒ์ฌ if (!isValid(date)) return "yoilError"; // ์ ํจํ์ง ์์ผ๋ฉด, /WEB-INF/views/yoilError.jsp๋ก ์ด๋ // 2. ์ฒ๋ฆฌ // char yoil = getYoil(date); // 3. Model์ ์์ ๊ฒฐ๊ณผ ์ ์ฅ // model.addAttribute("myDate", date); // model.addAttribute("yoil", yoil); // 4. ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค View์ ์ด๋ฆ์ ๋ฐํ return "yoil"; // /WEB-INF/views/yoil.jsp } private boolean isValid(MyDate date) { return isValid(date.getYear(), date.getMonth(), date.getDay()); } private @ModelAttribute("yoil") char getYoil(MyDate date) { // ๋ฉ์๋๊ฐ ์๋์ผ๋ก ํธ์ถ๋๊ณ ์ด ๊ฒฐ๊ณผ๊ฐ model์ ์ ์ฅ๋๋ค. return getYoil(date.getYear(), date.getMonth(), date.getDay()); } private char getYoil(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.set(year, month - 1, day); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); return " ์ผ์ํ์๋ชฉ๊ธํ ".charAt(dayOfWeek); } private boolean isValid(int year, int month, int day) { if (year == -1 || month == -1 || day == -1) return false; return (1 <= month && month <= 12) && (1 <= day && day <= 31); // ๊ฐ๋จํ ์ฒดํฌ } }

Uploaded by N2T