Back-End/Spring

์Šคํ”„๋ง์˜ ์ •์„ Ch2. 02 Spring MVC

์ฑ”๐Ÿป 2024. 1. 25. 12:05
๐Ÿ‘๐Ÿป

01. ์›๊ฒฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰

๋กœ์ปฌ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰

์›๊ฒฉ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰

= ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ์ปดํ“จํ„ฐ์— ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰

์‹คํ–‰ ๋ฐฉ๋ฒ•

์„œ๋ฒ„์— ์žˆ๋Š” ์›๊ฒฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ธŒ๋ผ์šฐ์ €์™€ WAS๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋ธŒ๋ผ์šฐ์ €์—์„œ http://111.222.333:8080์˜ URL ์ฃผ์†Œ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด,

ํ†ฐ์บฃ์—์„œ ์›๊ฒฉ์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ(๋ฉ”์„œ๋“œ)์„ ์‹คํ–‰์‹œํ‚ค๊ฒŒ๋œ๋‹ค.

์•„๋ฌด ํ”„๋กœ๊ทธ๋žจ์ด๋‚˜ ์›๊ฒฉ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

๐Ÿ’ก
1. ์›๊ฒฉ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•œ ํ”„๋กœ๊ทธ๋žจ ๋“ฑ๋ก(@Controller)
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();
    }
}
  1. http://localhost/requestInfo?bno=3 URL ์ž…๋ ฅ ํ›„ ํ˜ธ์ถœ ์‹œ
  1. ํ†ฐ์บฃ์ด HttpServletRequset ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
  1. ๊ฑฐ๊ธฐ์— ์š”์ฒญํ•œ ์ •๋ณด๋ฅผ ๋‹ด๋Š”๋‹ค.
  1. ํ†ฐ์บฃ์ด 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");

๊นŠ๊ฒŒX, ์•Œ์•„๋งŒ๋‘๊ธฐ

์œ„์˜ 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 + "์š”์ผ์ž…๋‹ˆ๋‹ค.");
        }
    }

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„

๐Ÿ’ก
ํด๋ผ์ด์–ธํŠธ(client) : ์„œ๋น„์Šค๋ฅผ ์š”์ฒญํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

์„œ๋ฒ„(server) : ์„œ๋น„์Šค(service)๋ฅผ ์ œ๊ณตํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

์„œ๋ฒ„์˜ ์ข…๋ฅ˜

์„œ๋ฒ„์˜ ์ข…๋ฅ˜๋Š” ์–ด๋–ค ์„œ๋น„์Šค๋ฅผ ํ•˜๋А๋ƒ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค.

์ด๋ฉ”์ผ ์„œ๋ฒ„ : ์ด๋ฉ”์ผ ์„œ๋น„์Šค ์ œ๊ณต

ํŒŒ์ผ ์„œ๋ฒ„ : ํŒŒ์ผ ์ œ๊ณต

์›น ์„œ๋ฒ„ : ์›น ์ œ๊ณต?โŒย ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด์„œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์„œ๋น„์Šค๋ฅผ ์ œ๊ณต(๋ฌธ์„œ, ์ด๋ฏธ์ง€, ๋™์˜์ƒ ๋ชจ๋‘ ์›น์„œ๋ฒ„๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์„œ๋น„์Šค๋‹ค.)

์„œ๋ฒ„์˜ ํฌํŠธ

1๋Œ€์˜ PC์— ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ IP๋กœ ์š”์ฒญ ์‹œ ํ•œ ๋Œ€์˜ PC์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์„œ๋ฒ„๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ์„œ๋ฒ„์— ๋Œ€ํ•œ ์š”์ฒญ์ธ์ง€ IP๋กœ๋งŒ์œผ๋ก  ๊ตฌ๋ถ„์„ ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

์ด๋•Œ ํ•„์š”ํ•œ ๊ฒƒ์ด ํฌํŠธ ๋ฒˆํ˜ธ๋‹ค. ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ ์–ด์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ํ•˜๋ฉด ํ•œ ๋Œ€์˜ PC์ค‘ ์–ด๋–ค ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฑด์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

WAS(์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„)๋ž€?

๐Ÿ’ก
์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„(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/server.xml : Tomcat ์„œ๋ฒ„ ์„ค์ • ํŒŒ์ผ

ํ†ฐ์บฃ์„ค์น˜๊ฒฝ๋กœ/conf/web.xml : Tomcat์˜ ๋ชจ๋“  web app์˜ ๊ณตํ†ต ์„ค์ •

์›น์•ฑ์ด๋ฆ„/WEB-INF/web.xml : web app์˜ ๊ฐœ๋ณ„ ์„ค์ •

โ€ป web app = ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

  • server.xml์—์„œ ๋ณด๋Š” ํ†ฐ์บฃ ๋‚ด๋ถ€ ๊ตฌ์กฐ

    unpackWARs=โ€trueโ€ ํ†ฐ์บฃ ์‹คํ–‰ ์‹œ war ํŒŒ์ผ์ด ์žˆ์œผ๋ฉด ์ž๋™์œผ๋กœ ์••์ถ•์„ ํ’€์–ด๋ผ

    ์ด ๋‘๊ฐ€์ง€๊ฐ€ ์›๋ž˜ web.xml์—์„œ ์„ค์ •ํ–ˆ์–ด์•ผ ํ–ˆ๋Š”๋ฐ ๋ถˆํŽธํ•ด์„œ ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค.

HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต

1. ํ”„๋กœํ† ์ฝœ(protocol)์ด๋ž€?

๐Ÿ’ก
์„œ๋กœ ๊ฐ„์˜ ํ†ต์‹ ์„ ์œ„ํ•œ ์•ฝ์†, ๊ทœ์น™
์ฃผ๊ณ  ๋ฐ›์„ Data์— ๋Œ€ํ•œ ํ˜•์‹์„ ์ •์˜ํ•œ ๊ฒƒ

Data๋ฅผ ์–ด๋–ป๊ฒŒ ์ฃผ๊ณ  ๋ฐ›์„์ง€ ๋ฏธ๋ฆฌ ์•ฝ์†ํ•˜์ง€ ์•Š์œผ๋ฉด Data๋ฅผ ๋ฐ›์•„๋„ ์ด๊ฒŒ ์–ด๋–ค ๋‚ด์šฉ์ธ์ง€ ํ•ด์„ํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ํ˜•์‹์œผ๋กœ Data๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„์ง€ ๋ฏธ๋ฆฌ ์•ฝ์†ํ•ด์•ผ ํ•œ๋‹ค.

์„œ๋กœ์˜ ์†Œํ†ต์„ ์œ„ํ•ด์„œ ๋ฏธ๋ฆฌ ์ •ํ•ด๋†“์€ ๊ทœ์น™ = ํ”„๋กœํ† ์ฝœ

โ‡’ ๊ทธ๋ƒฅ ์‰ฝ๊ฒŒ ํ”„๋กœํ† ์ฝœ์€ ์•ฝ์†, ๊ทœ์น™์ด๋ผ๊ณ  ์™ธ์šฐ์ž!

<์ดํ•ด๋ฅผ ๋•๊ธฐ์œ„ํ•œ ์‹ค์ƒํ™œ์—์„œ์˜ ์˜ˆ>

ํŽธ์ง€์˜ ๋ณด๋‚ด๋Š” ์‚ฌ๋žŒ ์œ„์น˜, ๋ฐ›๋Š” ์‚ฌ๋žŒ ์œ„์น˜, ์šฐํ‘œ ์œ„์น˜ ์ด๋Ÿฐ ๊ฒƒ๋“ค์ด ๋ฐ”๋กœ ํ”„๋กœํ† ์ฝœ์ด๋‹ค.

ํŽธ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ์‚ฌ๋žŒ, ๋ฐ›๋Š” ์‚ฌ๋žŒ, ๋ฐฐ๋‹ฌ ํ•˜๋Š” ์‚ฌ๋žŒ๋ผ๋ฆฌ ์ด๋Ÿฐ ํ”„๋กœํ† ์ฝœ(์‚ฌํšŒ์ ์ธ ํ•ฉ์˜)์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ๋ณ„๋‹ค๋ฅธ ์„ค๋ช… ์—†์ด ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

2. HTTP(Hyper Text Transfer Protocol)๋ž€?

ํ…์ŠคํŠธ ์ „์†ก ํ”„๋กœํ† ์ฝœ

โ‡’ ํ…์ŠคํŠธ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ(์•ฝ์†, ๊ทœ์น™)

โ€ป Hyper Text = HTML

<ํŠน์ง•>

  • ๋‹จ์ˆœํ•˜๊ณ  ์ฝ๊ธฐ ์‰ฝ๋‹ค. - ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜์˜ ํ”„๋กœํ† ์ฝœ
  • ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค.(stateless) - Client ์ •๋ณด๋ฅผ ์ €์žฅX

    ๊ฐ™์€ Client๊ฐ€ ์š”์ฒญ์„ ๋‘ ๋ฒˆ ๋ณด๋ƒˆ์„ ๋•Œ Server๋Š” ์ด ๋‘ ์š”์ฒญ์ด ๊ฐ™์€ Client๊ฐ€ ๋ณด๋‚ธ ๊ฒƒ์ธ์ง€ ๊ตฌ๋ณ„ ๋ชปํ•œ๋‹ค.

    Why? ํด๋ผ์ด์–ธํŠธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—

    โ†’ ์ด๋Ÿฐ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ฟ ํ‚ค์™€ ์„ธ์…˜์ด๋‹ค.(ํด๋ผ์ด์–ธํŠธ ๊ตฌ๋ณ„ ๊ฐ€๋Šฅํ•˜๊ฒŒ๋จ)

  • ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๋‹ค. - ์ปค์Šคํ…€ ํ—ค๋”(header) ์ถ”๊ฐ€ ๊ฐ€๋Šฅ

3. HTTP ๋ฉ”์‹œ์ง€

ํŽธ์ง€ํ•˜๊ณ  ๋น„์Šทํ•˜๋‹ค. ๋‘˜ ๋‹ค ํ…์ŠคํŠธ์ด๋‹ค.

ํ—ค๋” = ๋ณธ๋ฌธ์— ๋Œ€ํ•œ ์„ค๋ช… | ํŽธ์ง€์— ๋Œ€ํ•œ ์„ค๋ช….

๋ฐ”๋”” = ์‹ค์ œ ์ „๋‹ฌํ•  ๋‚ด์šฉ.

HTTP ํ”„๋กœํ† ์ฝœ์€ ์„œ๋กœ์—๊ฒŒ ์š”์ฒญ ํŽธ์ง€๋ฅผ ๋ณด๋‚ด๊ณ , ์ƒ๋Œ€๋ฐฉ์€ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ํŽธ์ง€๋ฅผ ๋ณด๋‚ธ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

์šฐ๋ฆฌ๋Š” URL๋งŒ ์ž…๋ ฅํ–ˆ์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ HTTP ์š”์ฒญ ๋ฉ”์‹œ์ง€๋ฅผ ๋งŒ๋“ค์–ด์„œ ์„œ๋ฒ„์—๊ฒŒ ์ „์†กํ•ด์ค€๋‹ค.

์‘๋‹ต ๋‚ด์šฉ์ด ๋ธŒ๋ผ์šฐ์ €์— Hello๋ผ๊ณ  ํ•ด์„๋˜์–ด ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค.

HTTP ๋ฉ”์‹œ์ง€ - ์‘๋‹ต ๋ฉ”์‹œ์ง€

HTTP ์‘๋‹ต ๋ฉ”์‹œ์ง€ foramt์— ๋งž์ถฐ์„œ ์ค˜์•ผ Client๊ฐ€ ๋‚ด์šฉ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒํƒœ ๋ผ์ธ = ์š”์ฒญ์ด ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ์•Œ๋ ค์ค€๋‹ค.

์ƒํƒœ ์ฝ”๋“œ ์˜†์—๋Š” ์„ค๋ช…

์•„๋ž˜์˜ ๊ธฐ๋ณธ์ ์ธ ์ƒํƒœ์ฝ”๋“œ๋Š” ์™ธ์›Œ์•ผ ํ•œ๋‹ค.

HTTP ์ƒํƒœ์ฝ”๋“œ์˜๋ฏธ์ƒ์„ธ ์„ค๋ช…
1xxInformationalHTTP/1.1 ์ถ”๊ฐ€ ์ •๋ณด ๊ตํ™˜
2xxSuccess์„ฑ๊ณต
3xxRedirect๋‹ค๋ฅธ URL ์š”์ฒญ
4xxClient Errorํด๋ผ์ด์–ธํŠธ ์ž˜๋ชป
5xxServer Error์„œ๋ฒ„ ์ž˜๋ชป

400๋ฒˆ๋Œ€ - Client Error

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ์ž˜๋ชปํ•œ ๊ฒƒ์ด๋‹ค. ์„œ๋ฒ„๋Š” ์ž˜๋ชปํ•œ ๊ฒƒ X

๋‚ด๊ฐ€ ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ

500๋ฒˆ๋Œ€ - Server Error

ํด๋ผ์ด์–ธํŠธ ์ž˜๋ชปX. ์„œ๋ฒ„ ์ž˜๋ชป.

๋‚˜๋Š” ์š”์ฒญ์„ ์ œ๋Œ€๋กœ ํ–ˆ๋Š”๋ฐ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋‹ค๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์ด๋‹ค.

HTTP ๋ฉ”์‹œ์ง€ - ์š”์ฒญ ๋ฉ”์‹œ์ง€

์ข…๋ฅ˜(๋Œ€ํ‘œ์ ์ธ ๊ฑฐ ๋‘๊ฐœ๋งŒ)

  1. GET - read

    ๋‹จ์ˆœํžˆ ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ฆ‰ ์ฝ๊ธฐ.

    ๋ฆฌ์†Œ์Šค URL๋งŒ ์ ์–ด์ฃผ๋ฉด ๋˜์–ด์„œ ๋ฐ”๋””๊ฐ€ ํ•„์š”์—†๊ณ  ํ—ค๋”๋งŒ ์กด์žฌํ•œ๋‹ค.

    Data๋ฅผ ๋ณด๋‚ผ ๊ฒŒ ์žˆ์œผ๋ฉด ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง์œผ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

  1. POST - write or ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ ์ œ๊ณต

    write, ๊ธ€์“ฐ๊ธฐ, ํšŒ์›๊ฐ€์ž…, ํŒŒ์ผ ์ฒจ๋ถ€, ์„œ๋ฒ„์— Data ์ œ๊ณต ์ด๋Ÿฐ ์šฉ๋„๋กœ ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์ด๋‹ค.

    POST๊ฐ™์€ ๊ฒฝ์šฐ๋Š” body๊ฐ€ ์žˆ์–ด์„œ GET์—์„œ ์ผ๋˜ ์ฟผ๋ฆฌ ์ŠคํŠธ๋ง์ด body์— ๋“ค์–ด๊ฐ„๋‹ค.

    โ†’ ์„œ๋ฒ„์— ์ „์†กํ•  Data๋ฅผ body์— ๋‹ด๋Š”๋‹ค.

HTTP ๋ฉ”์„œ๋“œ - GET, POST

GETPOST
์„ค๊ณ„ ๋ชฉ์ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์„ค๊ณ„์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด ์„ค๊ณ„
๋ฐ์ดํ„ฐ ์ „์†ก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 ํ”„๋กœํ† ์ฝœ๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•>

  1. MIME์œผ๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ทธ๋Œ€๋กœ ๋ณด๋‚ด๊ธฐ
  1. Base64๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด๋‚ธ๋‹ค.

    ๋‹จ์  : Data์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์ปค์ง„๋‹ค.

2. ๊ณตํ†ต ์ฝ”๋“œ์˜ ๋ถ„๋ฆฌ - ์ž…๋ ฅ์˜ ๋ถ„๋ฆฌ

3. ์ถœ๋ ฅ(view)์˜ ๋ถ„๋ฆฌ - ๋ณ€ํ•˜๋Š” ๊ฒƒ๊ณผ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์˜ ๋ถ„๋ฆฌ

4. MVC ํŒจํ„ด

์Šคํ”„๋ง MVC๊ฐ€ ์ด๋Ÿฐ ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ๋‹ค.

DispatcherServlet์ด ์•ž์—์„œ ์ž…๋ ฅ์ฒ˜๋ฆฌ, Model(๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•  ๊ฐ์ฒด)์„ ๋งŒ๋“  ๋‹ค์Œ์— ๊ทธ๊ฑธ Controller์—๊ฒŒ ๋„˜๊ฒจ์ค€๋‹ค. Controller๊ฐ€ ๊ทธ๊ฑธ ๋ฐ›๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด์„œ ์ฃผ๋ฉด ๊ทธ๊ฑธ Viewํ•œํ…Œ ์ „๋‹ฌํ•ด์ค€๋‹ค. ๋ทฐ์—์„œ๋Š” ์ž‘์—…ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ  ์ตœ์ข… ์‘๋‹ต์„ ๋งŒ๋“ค์–ด์„œ Client์—๊ฒŒ ๋ณด๋‚ธ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๋ทฐ๋กœ ๋ณด์—ฌ์ค€๋‹ค.

<MVC>

  1. ์ž…๋ ฅ๋ฐ›์„ ๊ฐ’๋“ค์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์„ ์–ธ.
  1. Model์„ ์„ ์–ธํ•ด์„œ ์ž‘์—…์„ ์ฒ˜๋ฆฌ
  1. Model์— ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅ
  1. ์ด ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค„ View ๋ฐ˜ํ™˜
  1. DispatcherServlet์ด ์ž‘์„ฑ ๊ฒฐ๊ณผ๊ฐ€ ์ €์žฅ๋˜์–ด์žˆ๋Š” Model์„ View์—๋‹ค ์ „๋‹ฌ.
  1. ๊ทธ๋ž˜์„œ 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. ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ํƒ€์ž…

<์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ํƒ€์ž…>

  1. ๋ทฐ์˜ ์ด๋ฆ„ ๋ฐ˜ํ™˜ O โ† ์ด๊ฑฐ๋ฅผ ์ œ์ผ ๋งŽ์ด ์“ด๋‹ค.
  1. ๋ทฐ์˜ ์ด๋ฆ„ ๋ฐ˜ํ™˜ 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";
      }
  1. 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 ํŒจํ„ด์˜ ์›๋ฆฌ

๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์–ป๋Š” ๋ฐฉ๋ฒ•

  1. ๋ฆฌํ”Œ๋ ‰์…˜ API

    -parameters ์˜ต์…˜์„ ๋„ฃ๊ณ  ์ปดํŒŒ์ผ์„ ํ•ด์•ผ ํ•œ๋‹ค. jdk1.8๋ถ€ํ„ฐ ๊ฐ€๋Šฅ

    javac -parameters ๋ช…๋ น์–ด์—์„œ -parameters ์˜ต์…˜์ด ๋น ์ง€๋ฉด ํด๋ž˜์ŠคํŒŒ์ผ์— ๋งค๊ฐœ๋ณ€์ˆ˜์ด๋ฆ„์„ ์ €์žฅํ•˜์ง€์•Š๋Š”๋‹ค

  1. 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. ์„œ๋ธ”๋ฆฟ๊ณผ ์ปจํŠธ๋กค๋Ÿฌ์˜ ๋น„๊ต

์„œ๋ธ”๋ฆฟ โ†’ ์Šคํ”„๋ง

  1. ์ƒ์† ์ œ๊ฑฐ๋จ
  1. ๋งค๊ฐœ๋ณ€์ˆ˜ ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์ ์œผ๋ฉด๋จ
  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์—ฌ๋„ ๊ดœ์ฐฎ์€ ๊ฒฝ์šฐ๋Š”

  1. ์ƒ์ˆ˜
  1. ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฉค๋ฒ„๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ์ด ๊ฐ์ฒด์— 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๊ฐ€์ง€๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  1. Singleton : default, 1๊ฐœ
  1. Prototype : ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด ์ƒ์„ฑ. iv ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Prototype์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์„œ๋ฒ„ ๋ถ€๋‹ด์ด ํฌ๊ธฐ ๋•Œ๋ฌธ์— ์›ฌ๋งŒํ•˜๋ฉด iv๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒŒ ์ข‹๋‹ค.(์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒฝ์šฐ๋Š” ์ œ์™ธ(1. ์ƒ์ˆ˜, 2. ํฌํ•จ ๊ด€๊ณ„์ธ๋ฐ ๊ทธ ๊ฐ์ฒด์— iv๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ)


Servlet Context : ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์— ํฌํ•จ๋œ ์„œ๋ธ”๋ฆฟ๋“ค์ด ์—ฌ๊ธฐ ๋‹ค ๋“ฑ๋ก๋˜์–ด์žˆ๋‹ค.

4. JSP์™€ ์„œ๋ธ”๋ฆฟ์˜ ๋น„๊ต

5. JSP์˜ ํ˜ธ์ถœ ๊ณผ์ •

6. JSP์™€ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋ณ€ํ™˜๋œ JSP ๋น„๊ต

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

๊ธฐ๋ณธ ๊ฐ์ฒดํƒ€์ž…์„ค๋ช…
requestjavax.servlet.http.HttpServletRequest์š”์ฒญ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š” ๊ฐ์ฒด
responsejavax.servlet.http.HttpServletResponse์š”์ฒญ์— ์‘๋‹ต์„ ์ž‘์„ฑํ•  ๋•Œ ์‚ฌ์šฉ
sessionjavax.servlet.http.HttpSessionHTTP session์„ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด. ์„ธ์…˜ ์ •๋ณด ์ €์žฅ์— ์‚ฌ์šฉ
applicationjavax.servlet.ServletContextWeb Application ์ „์ฒด์—์„œ ๊ณต์œ ํ•˜๋Š” ๊ฐ์ฒด
configjavax.servlet.ServletConfigJSP ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์„ค์ • ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด
pagejava.lang.ObjectJSP ํŽ˜์ด์ง€ ๊ฐ์ฒด ์ž์‹ 
pageContextjavax.servlet.jsp.PageContextJSPํŽ˜์ด์ง€์˜ context์ •๋ณด๋ฅผ ์ œ๊ณต
outjavax.servlet.jsp.JspWriter์‘๋‹ต์— ํฌํ•จ๋  ๋‚ด์šฉ์„ ์ถœ๋ ฅํ•  ๋•Œ ์‚ฌ์šฉ
exceptionjava.lang.Throwable์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ƒ์„ฑ๋˜๋Š” ์˜ˆ์™ธ ๊ฐ์ฒด

8. ์œ ํšจ ๋ฒ”์œ„(scope)์™€ ์†์„ฑ(attribute)

<4๊ฐœ ์ €์žฅ์†Œ>

  1. ์ ‘๊ทผ ๋ฒ”์œ„
  1. ์ƒ์กด ๊ธฐ๊ฐ„

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 ์ •๋ฆฌ

๊ธฐ๋ณธ ๊ฐ์ฒด์œ ํšจ ๋ฒ”์œ„์„ค๋ช…
pageContext1๊ฐœ JSPํŽ˜์ด์ง€JSPํŽ˜์ด์ง€์˜ ์‹œ์ž‘๋ถ€ํ„ฐ ๋๊นŒ์ง€. ํ•ด๋‹น JSP ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘๊ทผ๊ฐ€๋Šฅ. ํŽ˜์ด์ง€๋‹น 1๊ฐœ
request1+๊ฐœ JSPํŽ˜์ด์ง€์š”์ฒญ์˜ ์‹œ์ž‘๋ถ€ํ„ฐ ์‘๋‹ต๊นŒ์ง€. ๋‹ค๋ฅธ JSP๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅ. ์š”์ฒญ๋งˆ๋‹ค 1๊ฐœ
sessionn๊ฐœ JSPํŽ˜์ด์ง€session์˜ ์‹œ์ž‘๋ถ€ํ„ฐ ์ข…๋ฃŒ๊นŒ์ง€(๋กœ๊ทธ์ธ ~ ๋กœ๊ทธ์•„์›ƒ). ํด๋ผ์ด์–ธํŠธ๋งˆ๋‹ค 1๊ฐœ
applicationcontext ์ „์ฒด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๋กœ ์˜ฎ๊ธด ๊ฒƒ

  • ๋กœ๊น…

    ์–ด๋–ค ์š”์ฒญ์ด ๋“ค์–ด์™”๋Š”์ง€ ๋‹ค ๋ณผ ์ˆ˜ ์žˆ๋‹ค. โ†’ ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋–ค ํŽ˜์ด์ง€์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜ ๋จธ๋ฌผ๋ €๋Š”์ง€ ํ†ต๊ณ„๋‚ด๊ธฐ ๊ฐ€๋Šฅ

  • 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]
     */
  1. ์š”์ฒญํ•œ ๊ฐ’๋“ค์ด HashMap์œผ๋กœ ๋“ค์–ด์˜จ๋‹ค.(๋‹ด๊ธด๋‹ค.)
  1. 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());
  }

์ปจํŠธ๋กค๋Ÿฌ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ถ™์ด๋Š” ์• ๋„ˆํ…Œ์ด์…˜

  1. @RequestParam : ๊ธฐ๋ณธํ˜•, String(์ƒ๋žต ๊ฐ€๋Šฅ)

    ์ฐธ์กฐํ˜• ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ์—๋Š” ์ด ์• ๋„ˆํ…Œ์ด์…˜ ๋ชป ๋ถ™์ž„. ์—ฌ๋Ÿฌ ๊ฐ’์ด ๋ฐ”์ธ๋”ฉ๋˜๊ธฐ ๋•Œ๋ฌธ.

    ๊ธฐ๋ณธํ˜•์ด๋‚˜ String ๊ฐ™์€ ๊ฒฝ์šฐ ๊ตณ์ด ๋ชจ๋ธ์— ์ €์žฅํ•  ํ•„์š”X ๋ทฐ์—์„œ ${param.ํŒŒ๋ผ๋ฏธํ„ฐ์ด๋ฆ„}์œผ๋กœ ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  1. @ModelAttribute : ์ฐธ์กฐํ˜•(์ƒ๋žต ๊ฐ€๋Šฅ, ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ถ™์–ด์žˆ๋‹ค๊ณ  ๋ณด๋ฉด๋จ)

3. WebDataBinder

: ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด์„œ ์š”์ฒญ๋ฐ›์€ ๊ฐ’์ด ์‹ค์ œ ๊ฐ์ฒด์— Binding๋  ๋•Œ ์ค‘๊ฐ„ ์—ญํ• ์„ ํ•ด์ฃผ๋Š” ๊ฒƒ

String์œผ๋กœ ๋„˜์–ด์˜จ ๊ฑธ ๋ณ€ํ™˜ํ•ด์ฃผ๊ณ  ๊ฒ€์ฆํ•ด์ฃผ๋Š” ์• 

์—ญํ• 

  1. ํƒ€์ž… ๋ณ€ํ™˜
  1. ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ
  1. ๊ฒฐ๊ณผ(BindingResult์— ์ €์žฅ)
  1. 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