[MVC] controller

Updated:

Categories:

Tags: , ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]

Spring MVC

  • ์Šคํ”„๋ง์€ ์„œ๋ธ”๋ฆฟ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•จ.
  • Spring์˜ ๋ชจ๋“ˆ ์ค‘์—์„œ ์„œ๋ธ”๋ฆฟ(Servlet) API๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“ˆ์ด ๋ฐ”๋กœ spring-webmvc = Spring MVC = Spring MVC ํ”„๋ ˆ์ž„์›Œํฌ
    • ์„œ๋ธ”๋ฆฟ : ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํŠน์ • ๊ทœ์•ฝ์— ๋งž์ถ”์–ด์„œ Java ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š”ํด๋ž˜์Šค ํŒŒ์ผ
    • ์•„ํŒŒ์น˜ ํ†ฐ์บฃ(Apache Tomcat)์€ ์ด๋Ÿฌํ•œ ์„œ๋ธ”๋ฆฟ๋“ค์ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹คํ–‰์ด ๋˜๋„๋ก ํ•ด์ฃผ๋Š” ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ(Servlet Container) ์ค‘ ํ•˜๋‚˜

M

Model์€ Spring MVC์—์„œ M์— ํ•ด๋‹น

์ฒ˜๋ฆฌํ•œ ์ž‘์—…์˜ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ด๋•Œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค์ฃผ๋Š” ์ž‘์—…์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ Model

ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ ์‚ฌํ•ญ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜์—ญ์„ ์„œ๋น„์Šค ๊ณ„์ธต(Service Layer)์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ์‹ค์ œ๋กœ ์š”์ฒญ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Java ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ์„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(Business Logic)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

V

View๋Š” Spring MVC์—์„œ V์— ํ•ด๋‹น

View๋Š” ์•ž์—์„œ ์„ค๋ช…ํ•œ Model ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด์„œ ์›น๋ธŒ๋ผ์šฐ์ € ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ฆฌ์†Œ์Šค(Resource)๋ฅผ ์ œ๊ณตํ•˜๋Š” ์—ญํ• 

  • HTML ํŽ˜์ด์ง€์˜ ์ถœ๋ ฅ
  • Spring MVC์—์„œ ์ง€์›ํ•˜๋Š” HTML ํŽ˜์ด์ง€ ์ถœ๋ ฅ ๊ธฐ์ˆ ์—๋Š” Thymeleaf, FreeMarker, JSP + JSTL, Tiles ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

โ‡’ ์•ž์œผ๋กœ V๋Š” ์•ˆํ•˜๊ณ  jsonํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค ์˜ˆ์ •

๐Ÿ’™ JSON(JavaScript Object Notation)์ด๋ž€?

C

Controller๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์š”์ฒญ์„ ์ง์ ‘์ ์œผ๋กœ ์ „๋‹ฌ๋ฐ›๋Š” ์—”๋“œํฌ์ธํŠธ(Endpoint)๋กœ์จ Model๊ณผ View์˜ ์ค‘๊ฐ„์—์„œ ์ƒํ˜ธ ์ž‘์šฉ์„ ํ•ด์ฃผ๋Š” ์—ญํ• 

์ฆ‰, ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์š”์ฒญ์„ ์ „๋‹ฌ๋ฐ›์•„์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ฑฐ์นœ ํ›„์— Model ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด, ์ด Model ๋ฐ์ดํ„ฐ๋ฅผ View๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping(path = "/v1/coffee")
public class CoffeeController {
    private final CoffeeService coffeeService;

    CoffeeController(CoffeeService coffeeService) {
        this.coffeeService = coffeeService;
    }

    @GetMapping("/{coffee-id}")  // (1)
    public Coffee getCoffee(@PathVariable("coffee-id") long coffeeId) {
        return coffeeService.findCoffee(coffeeId); // (2)
    }
}

  • (1)์˜ @GetMapping ์• ๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์š”์ฒญ์„ ์ˆ˜์‹ 
  • (2)์—์„œ CoffeeService ํด๋ž˜์Šค์˜ findCoffee() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌ
  • (2)์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ๋ฆฌํ„ด ๋ฐ›๋Š” Coffee๊ฐ€ ์—ฌ๊ธฐ์„œ๋Š” Model ๋ฐ์ดํ„ฐ

MVC์˜ ์ „์ฒด์ ์ธ ๋™์ž‘ํ๋ฆ„

  • Client๊ฐ€ ์š”์ฒญ ๋ฐ์ดํ„ฐ ์ „์†ก

    โ†’ Controller๊ฐ€ ์š”์ฒญ ๋ฐ์ดํ„ฐ ์ˆ˜์‹  โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ โ†’ Model ๋ฐ์ดํ„ฐ ์ƒ์„ฑ

    โ†’ Controller์—๊ฒŒ Model ๋ฐ์ดํ„ฐ ์ „๋‹ฌ โ†’ Controller๊ฐ€ View์—๊ฒŒ Model ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

    โ†’ View๊ฐ€ ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ƒ์„ฑ

Spring MVC์˜ ๋™์ž‘ ๋ฐฉ์‹๊ณผ ๊ตฌ์„ฑ ์š”์†Œ ( ์™„์ „ ์ค‘์š” โœจโœจโœจโœจ)

  • ์ง์ ‘ ๋‹ค๋ฃจ์ง€๋Š” ์•Š์•„๋„ ํ๋ฆ„์ด ์ด๋ ‡๋‹ค๋Š” ๊ฒƒ์€ ๊ผญ ์•Œ์•„์•ผ ํ•จ.

    1. ์š”์ฒญ์ „์†กํ•˜๋ฉด ๋ฐ”๋กœ Controller๋กœ ๊ฐ€์ง€์•Š์Œ - DispatcherServlet ์ด ์š”์ฒญ์„ ๋ฐ›์Œ.
    2. DispatcherServlet์ด handlerMapping์—๊ฒŒ ๋ณด๋ƒ„(ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Controller์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰์„ ์š”์ฒญ). โ†’ handlerMapping์ด ์ปจํŠธ๋กค๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋‹ค ์•Œ๊ณ  ์žˆ์Œ. controller ์ฐพ์•„์„œ ์•Œ๋ ค์คŒ
    3. HandlerMapping์€ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ๊ณผ ๋งคํ•‘๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ๋ฆฌํ„ด
    4. DispatcherServlet์€ Handler ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ , HandlerAdpater์—๊ฒŒ Handler ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์œ„์ž„
    5. HandlerAdapter๋Š” DispatcherServlet์œผ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ Controller ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น Controller์˜ Handler ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
    6. Controller์˜ Handler ๋ฉ”์„œ๋“œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ ํ›„ ๋ฆฌํ„ด ๋ฐ›์€ Model ๋ฐ์ดํ„ฐ๋ฅผ HandlerAdapter์—๊ฒŒ ์ „๋‹ฌ
    7. HandlerAdapter๋Š” ์ „๋‹ฌ๋ฐ›์€ Model ๋ฐ์ดํ„ฐ์™€ View ์ •๋ณด๋ฅผ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ์ „๋‹ฌ
    8. DispatcherServlet์€ ์ „๋‹ฌ๋ฐ›์€ View ์ •๋ณด๋ฅผ ๋‹ค์‹œ ViewResolver์—๊ฒŒ ์ „๋‹ฌํ•ด์„œ View ๊ฒ€์ƒ‰์„ ์š”์ฒญ
    9. ViewResolver๋Š” View ์ •๋ณด์— ํ•ด๋‹นํ•˜๋Š” View๋ฅผ ์ฐพ์•„์„œ View๋ฅผ ๋‹ค์‹œ ๋ฆฌํ„ด
    10. DispatcherServlet์€ ViewResolver๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ View ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด Model ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•  ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ƒ์„ฑ์„ ์š”์ฒญ
    11. View๋Š” ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ์ „๋‹ฌ
    12. DispatcherServlet์€ View๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌ
  • DispatcherServlet์˜ ์—ญํ• 

    • ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ์š”์ฒญ์„ ์ „๋‹ฌ ๋ฐ›์œผ๋ฉด HandlerMapping, HandlerAdapter, ViewResolver, View ๋“ฑ ๋Œ€๋ถ€๋ถ„์˜ Spring MVC ๊ตฌ์„ฑ ์š”์†Œ๋“ค๊ณผ ์ƒํ˜ธ ์ž‘์šฉ์„ ํ•จ
    • ๋ฐ”๋น ๋ณด์ด์ง€๋งŒ ์‹ค์ œ๋กœ ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Š” ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ๋“ค์—๊ฒŒ ์œ„์ž„(Delegate)ํ•˜๊ณ  ์žˆ์Œ.
    • DispatcherServlet์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐ€์žฅ ์•ž๋‹จ์— ๋ฐฐ์น˜๋˜์–ด ๋‹ค๋ฅธ ๊ตฌ์„ฑ์š”์†Œ๋“ค๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํŒจํ„ด์„ Front Controller Pattern์ด๋ผ๊ณ  ํ•œ๋‹ค.

Controller

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹ค์Šต์œผ๋กœ MVC ๋ฐฐ์šฐ๊ธฐ

[์š”๊ตฌ์กฐ๊ฑด]


  • ์ฃผ์ธ์ด ์ปคํ”ผ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ •๋ณด ๋“ฑ๋ก ๊ธฐ๋Šฅ
    • ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์ˆ˜์ • ๊ธฐ๋Šฅ
    • ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์‚ญ์ œ ๊ธฐ๋Šฅ
    • ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์กฐํšŒ ๊ธฐ๋Šฅ
  • ๊ณ ๊ฐ์ด ์ปคํ”ผ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ •๋ณด ์กฐํšŒ ๊ธฐ๋Šฅ
  • ๊ณ ๊ฐ์ด ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ•˜๋Š” ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ฃผ๋ฌธ ๋“ฑ๋ก ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ฃผ๋ฌธ ์ทจ์†Œ ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ฃผ๋ฌธ ์กฐํšŒ ๊ธฐ๋Šฅ

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค

  • ๊ณ ๊ฐ์ด ์ฃผ๋ฌธํ•œ ์ปคํ”ผ๋ฅผ ์ฃผ์ธ์ด ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ
    • ์ปคํ”ผ ์ฃผ๋ฌธ ์กฐํšŒ ๊ธฐ๋Šฅ
    • ๊ณ ๊ฐ์—๊ฒŒ ์ „๋‹ฌ ์™„๋ฃŒํ•œ ์ปคํ”ผ์— ๋Œ€ํ•œ ์ฃผ๋ฌธ ์™„๋ฃŒ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ

Controller ์„ค๊ณ„

  • REST API ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ œ๊ณตํ•ด์•ผ ๋  ๊ธฐ๋Šฅ์„ ๋ฆฌ์†Œ์Šค(Resource, ์ž์›)๋กœ ๋ถ„๋ฅ˜
  • ์ปคํ”ผ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•œ Resourse๋Š” ํšŒ์›/์ปคํ”ผ/์ฃผ๋ฌธ ์— ํ•ด๋‹น
  • ์ฃผ์ธ์˜ ๊ธฐ๋Šฅ์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์•ผ ๋˜๋Š” ๊ฒƒ ์•„๋‹ˆ๋ƒ๋Š” ์˜๋ฌธ์ด ๋“ค ์ˆ˜๋„ ์žˆ์ง€๋งŒ

    โ†’ ๊ณ ๊ฐ๊ณผ ์ฃผ์ธ์˜ ์ธ์ฆ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ณต์žกํ•ด์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ

    โ†’ ์‹ค์ œ ํฐ ์—…์ฒด์—๋Š” ๋ฐฑ์˜คํ”ผ์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์‚ฌ์šฉํ•จ

ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ์ƒ์„ฑ

์™ผ์ชฝ์€ ๊ธฐ๋Šฅ ๊ธฐ๋ฐ˜, ์˜ค๋ฅธ์ชฝ์€ ๊ณ„์ธต ๊ธฐ๋ฐ˜

๊ณ„์ธต ๊ธฐ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ธฐ๋Šฅ ๊ธฐ๋ฐ˜ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆŒ ์˜ˆ์ •์ž„.

โ†’ ์™œ๋ƒ๋ฉด ? Spring Boot ํŒ€์—์„œ๋Š” ํ…Œ์ŠคํŠธ์™€ ๋ฆฌํŒฉํ† ๋ง์ด ์šฉ์ดํ•˜๊ณ , ํ–ฅํ›„์— ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค ์‹œ์Šคํ…œ์œผ๋กœ์˜ ๋ถ„๋ฆฌ๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ์šฉ์ดํ•œ ๊ธฐ๋Šฅ ๊ธฐ๋ฐ˜ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ

์—”ํŠธ๋ฆฌํฌ์ธํŠธ(Entrypoint) ํด๋ž˜์Šค ์ž‘์„ฑ

@SpringBootApplication

  • ์ž๋™ ๊ตฌ์„ฑ์„ ํ™œ์„ฑํ™”
  • @Component๊ฐ€ ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ๊ฒ€์ƒ‰ํ•œ ํ›„(scan), Spring Bean์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”
  • @Configuration ์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ ์ฐพ์•„์ฃผ๊ณ , ์ถ”๊ฐ€์ ์œผ๋กœ Spring Bean์„ ๋“ฑ๋กํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”

SpringApplication.run(SpringStartApplication.class, args);

  • Spring ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ถ€ํŠธ์ŠคํŠธ๋žฉํ•˜๊ณ , ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•จ

๋ถ€ํŠธ์ŠคํŠธ๋žฉ(Bootstrap)์ด๋ž€?

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์„ค์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋งŒ๋“œ๋Š” ๋‹จ๊ณ„๋ฅผ ์˜๋ฏธ

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Controller ๊ตฌ์กฐ ์ž‘์„ฑ

  1. MemberController ๊ตฌ์กฐ ์ž‘์„ฑ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     package com.springboot.member;
        
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.RestController;
        
     @RestController
     @RequestMapping("/v1/members")
     public class MemberController {
     }
    
    1. @RestController โ‡’ ์Šคํ”„๋ง์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋“ฑ๋ก์‹œ์ผœ์คŒ๊ณผ ๋™์‹œ์— ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๊ตฌํ˜„ํ•  ๊ฑฐ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๋ฆผ

    2. ํ•ด๋‹น ์ฃผ์†Œ(/v1/members)๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ MemberController๊ฐ€ ๋‹ด๋‹น

  2. OrderController ๊ตฌ์กฐ ์ž‘์„ฑ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     package com.springboot.order;
        
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.RestController;
        
     @RestController
     @RequestMapping("/v1/orders")
     public class OrderController {
     }
    
  3. CoffeeController ๊ตฌ์กฐ ์ž‘์„ฑ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     package com.springboot.coffee;
        
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.RestController;
        
     @RestController
     @RequestMapping("/v1/coffees")
     public class CoffeeController {
        
     }
    

ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(Handler Method)

  • ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ „๋‹ฌ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์š”์ฒญ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ(Request Handler Method)๊ฐ€ ํ•„์š”

  • Postman ์‚ฌ์šฉ๋ฒ• : https://itvillage.tistory.com/38
  • ํ•˜๊ธฐ ์ฝ”๋“œ์— ๋‚˜์˜ค๋Š” annotation์€ ๋งํฌ ์ฐธ์กฐ, ๋”ฐ๋กœ ์ •๋ฆฌํ•  ์˜ˆ์ •!

    โ†’ https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods.html

1 - ๋ ˆ๊ฑฐ์‹œ์ฝ”๋“œ

  1. MemberController

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    
     package com.springboot.member;
     import org.springframework.http.MediaType;
     import org.springframework.web.bind.annotation.*;
        
     @RestController
     @RequestMapping(value = "/v1/members", produces = {MediaType.APPLICATION_JSON_VALUE})
     public class MemberController {
         @PostMapping
         public String postMember(@RequestParam("email") String email,
                                  @RequestParam("name") String name,
                                  @RequestParam("phone") String phone) {
             System.out.println("# email: " + email);
             System.out.println("# name: " + name);
             System.out.println("# phone: " + phone);
        
             String response =
                     "{\"" +
                             "email\":\"" + email + "\"," +
                             "\"name\":\"" + name + "\"," +
                             "\"phone\":\"" + phone +
                             "\"}";
             return response;
         }
        
         @GetMapping("/{member-id}")
         public String getMember(@PathVariable("member-id")long memberId) {
             System.out.println("# memberId: " + memberId);
        
             // not implementation
             return null;
         }
        
         @GetMapping
         public String getMembers() {
             System.out.println("# get Members");
        
             // not implementation
             return null;
         }
     }
        
    

    1) postMember() ๋ฉ”์„œ๋“œ๋Š” ํšŒ์› ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•ด ์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ

    2) @PostMapping

    ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ ๋ฐ์ดํ„ฐ(request body)๋ฅผ ์„œ๋ฒ„์— ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜, ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์š”์ฒญ ์ „์†ก ์‹œ, HTTP Method ํƒ€์ž…์„ ๋™์ผํ•˜๊ฒŒ ๋งž์ถฐ์ฃผ์–ด์•ผ ํ•จ.

    3) @RequestParam

    ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ข…๋ฅ˜ ์ค‘ ํ•˜๋‚˜, ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์ „์†กํ•˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ(Query Parmeter ๋˜๋Š” Query String), ํผ ๋ฐ์ดํ„ฐ(form-data), x-www-form-urlencoded ํ˜•์‹์œผ๋กœ ์ „์†กํ•˜๋ฉด ์ด๋ฅผ ์„œ๋ฒ„ ์ชฝ์—์„œ ์ „๋‹ฌ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜

    4) ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†ก๋ฐ›์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‘๋‹ต ๋ฌธ์ž์—ด์„ JSON ํ˜•์‹์— ๋งž๊ฒŒ ์ž‘์„ฑ

    1. Postman : postMember() ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋งคํ•‘ URI๋กœ์˜ ์š”์ฒญ/์‘๋‹ต ๋ชจ์Šต

    6) GetMapping

    ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ๋ฆฌ์†Œ์Šค๋ฅผ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์• ๋„ˆํ…Œ์ด์…˜

    7) PathVariable :

    ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ข…๋ฅ˜ ์ค‘ ํ•˜๋‚˜, ๊ด„ํ˜ธ ์•ˆ์— ์ž…๋ ฅํ•œ ๋ฌธ์ž์—ด ๊ฐ’์€ @GetMapping("/{member-id}")์ฒ˜๋Ÿผ ์ค‘๊ด„ํ˜ธ({ }) ์•ˆ์˜ ๋ฌธ์ž์—ด๊ณผ ๋™์ผํ•ด์•ผ ํ•จ,

    ๋‘ ๋ฌธ์ž์—ด์ด ๋‹ค๋ฅด๋‹ค๋ฉด MissingPathVariableException์ด ๋ฐœ์ƒ

    7) GetMember

    getMember() ๋ฉ”์„œ๋“œ๋Š” ํŠน์ • ํšŒ์›์˜ ์ •๋ณด๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ชฝ์— ์ œ๊ณตํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ

    7) GetMembers

    • ํšŒ์› ๋ชฉ๋ก์„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ
    • @GetMapping ์—๋Š” ๋ณ„๋„์˜ URI๋ฅผ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค ๋ ˆ๋ฒจ์˜ URI(โ€œ/v1/membersโ€)์— ๋งคํ•‘
  2. OrderController

    โœ”๏ธ ์š”์ฒญ์— ํ•„์š”ํ•œ ์ฃผ๋ฌธ(Order) ์ •๋ณด

    • ํšŒ์› ์‹๋ณ„์ž: memberId
    • ์ปคํ”ผ ์‹๋ณ„์ž: coffeeId
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    
     package com.springboot.order;
        
     import org.springframework.http.MediaType;
     import org.springframework.web.bind.annotation.*;
        
     @RestController
     @RequestMapping(value = "/v1/orders", produces = MediaType.APPLICATION_JSON_VALUE)
     public class OrderController {
         @PostMapping
         public String postOrder(@RequestParam("memberId") long memberId,
                                 @RequestParam("coffeeId") long coffeeId) {
             System.out.println("# memberId: " + memberId);
             System.out.println("# coffeeId: " + coffeeId);
        
             String response =
                     "{\\"" +
                         "memberId\\":\\""+memberId+"\\"," +
                         "\\"coffeeId\\":\\""+coffeeId+"\\"" +
                     "}";
             return response;
         }
        
         @GetMapping("/{order-id}")
         public String getOrder(@PathVariable("order-id") long orderId) {
             System.out.println("# orderId: " + orderId);
        
             // not implementation
             return null;
         }
        
         @GetMapping
         public String getOrders() {
             System.out.println("# get Orders");
        
             // not implementation
             return null;
         }
     }
        
    

    1) postOrder() ๋ฉ”์„œ๋“œ๋Š” ํšŒ์› ๊ณ ๊ฐ์ด ์ฃผ๋ฌธํ•œ ์ปคํ”ผ ์ฃผ๋ฌธ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•ด ์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ

    • ๊ณ ๊ฐ์ด ์ฃผ๋ฌธํ•œ ์ปคํ”ผ์— ํ•„์š”ํ•œ ์ฃผ๋ฌธ ์ •๋ณด๋Š” ์–ด๋–ค ๊ณ ๊ฐ์ด ์–ด๋–ค ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ–ˆ๋А๋ƒ ํ•˜๋Š” ๊ฒƒ
    • โ€˜์–ด๋–ค ๊ณ ๊ฐโ€™์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๊ฐ€ ํšŒ์› ์‹๋ณ„์ž(memberId)
    • โ€˜์–ด๋–ค ์ปคํ”ผโ€™์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๊ฐ€ ๋ฐ”๋กœ ์ปคํ”ผ ์‹๋ณ„์ž(coffeeId)

๊ฐœ์„  ํฌ์ธํŠธ

  1. ์ œ์ผ ๋ถˆํŽธํ•œ ๊ฒƒ response

    โ‡’ JSON ๋ฌธ์ž์—ด ์ˆ˜์ž‘์—…์„ Map ๊ฐ์ฒด๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๊ฐœ์„  ๊ฐ€๋Šฅ

    โ‡’ ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ Ex) return new ResponseEntity<>(HttpStatus.OK);

  2. @RequestParam ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ์ˆ˜์‹ 

    โ‡’ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์ด ๋‹ค์„ฏ ๊ฐœ๋ผ๋ฉด ์ด ๋‹ค์„ฏ ๊ฐœ์˜ @RequestParameter๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ž…๋ ฅ

2 - ResponseEntity ์ ์šฉ

๊ธฐ์กด 1์˜ ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์—์„œ ๊ฐ€์žฅ ๋ถˆํŽธํ–ˆ๋˜ ๋ถ€๋ถ„์„ ๊ฐœ์„ ํ•œ ์ฝ”๋“œ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/v1/members") // (1) produces ์„ค์ • ์ œ๊ฑฐ๋จ
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        // (2) JSON ๋ฌธ์ž์—ด ์ˆ˜์ž‘์—…์„ Map ๊ฐ์ฒด๋กœ ๋Œ€์ฒด
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);

        // (3) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(map, HttpStatus.CREATED);
    }

    @GetMapping("/{member-id}")
    public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation

        // (4) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity getMembers() {
        System.out.println("# get Members");

        // not implementation

        // (5) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(HttpStatus.OK);
    }
}

  1. @RequestMapping์˜ โ€˜producesโ€™ ์˜ attribute ์‚ฌ๋ผ์ง.
  2. JSON ๋ฌธ์ž์—ด์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ˆ˜์ž‘์—…์œผ๋กœ ์ž‘์„ฑํ•˜๋˜ ๋ถ€๋ถ„์ด Map ๊ฐ์ฒด๋กœ ๋Œ€์ฒด

    โ†’ ์ด๋ฅผ ํ†ตํ•ด @RequestMapping์˜ โ€˜producesโ€™ attribute๋ฅผ ์ƒ๋žต๊ฐ€๋Šฅํ•ด์ง

    โ†’ Map ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๊ฒŒ ๋˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ โ€˜์ด ๋ฐ์ดํ„ฐ๋Š” JSON ํ˜•์‹์˜ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ๋˜๋Š”๊ตฌ๋‚˜โ€™๋ผ๊ณ  ์ดํ•ดํ•˜๊ณ  JSON ํ˜•์‹์œผ๋กœ ์ž๋™ ๋ณ€ํ™˜ํ•ด์คŒ

  3. ๋ฆฌํ„ด ๊ฐ’์œผ๋กœ JSON ๋ฌธ์ž์—ด์„ ๋ฆฌํ„ดํ•˜๋˜ ๋ถ€๋ถ„์ด ResponseEntity ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ด
    • new ResponseEntity<>(map, HttpStatus.CREATED);์ฒ˜๋Ÿผ ResponseEntity ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ์ƒ์„ฑ์ž ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‘๋‹ต ๋ฐ์ดํ„ฐ(map)์™€ HTTP ์‘๋‹ต ์ƒํƒœ๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌ
    • HTTP ์‘๋‹ต ์ƒํƒœ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์„œ๋ฒ„๊ฐ€ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ–ˆ๋Š”์ง€๋ฅผ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Œ
    • ResponseEntity ์ฐธ๊ณ ๋งํฌ : https://itvillage.tistory.com/44
  4. (4), (5) getMember(), getMembers() ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ์—ญ์‹œ ResponseEntity ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฑธ๋กœ ์ˆ˜์ •ํ•˜์˜€์œผ๋ฉฐ, HttpStatus.OK ์‘๋‹ต ์ƒํƒœ๋ฅผ ์ „๋‹ฌํ•˜๋„๋ก ์ˆ˜์ •
  5. Postman ๊ฒฐ๊ณผ - postMember() ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ์š”์ฒญ

    • POST Method ํ˜•์‹์˜ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ์ƒํƒœ๋Š” HttpStatus.OK๋ณด๋‹ค๋Š” HttpStatus.CREATED๊ฐ€ ์กฐ๊ธˆ ๋” ์ž์—ฐ์Šค๋Ÿฌ

HTTP ํ—ค๋”(Header)

  • HTTP ๋ฉ”์‹œ์ง€(Messages)์˜ ๊ตฌ์„ฑ ์š”์†Œ ์ค‘ ํ•˜๋‚˜๋กœ์จ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด๋‚˜ ์„œ๋ฒ„์˜ ์‘๋‹ต์— ํฌํ•จ๋˜์–ด ๋ถ€๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ HTTP ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ.
  • ๊ฐœ๋ฐœ์ž๊ฐ€ ํ—ค๋”๋ฅผ ๊ฑด๋“œ๋ฆด ์ผ์€ ๋งŽ์ด ์—†์ง€๋งŒ, ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ ์ง์ ‘ ์ปจํŠธ๋กค ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ
    1. Authorization
    1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ ์ ˆํ•œ ์ž๊ฒฉ ์ฆ๋ช…์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์ •๋ณด
    2. REST API ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์˜ ๋กœ๊ทธ์ธ(์‚ฌ์šฉ์ž ID/๋น„๋ฐ€๋ฒˆํ˜ธ) ์ธ์ฆ์— ํ†ต๊ณผํ•œ ํด๋ผ์ด์–ธํŠธ๋“ค์€ โ€˜Authorizationโ€™ ํ—ค๋” ์ •๋ณด๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธ์ฆ์— ํ†ต๊ณผํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์นจ
      1. User-Agent
    3. ๋ฐ์Šคํฌํ†ฑ, ๋…ธํŠธ๋ถ. ์Šค๋งˆํŠธํฐ, ํƒœ๋ธ”๋ฆฟ ๋“ฑ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ๊ตฌ๋ถ„ํ•ด์„œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๋ณด๋‚ด์ค˜์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ ๊ตฌ๋ถ„ํ•ด์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์คŒ.
    4. ํŠนํžˆ ๊ฐค๋Ÿญ์‹œ ํด๋“œ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ํ™”๋ฉด ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ์ฒดํฌํ•ด์„œ ๋‚ด๋ณด๋‚ด์•ผ ํ•จ.

HTTP Request ํ—ค๋” ์ •๋ณด ์–ป๊ธฐ

Spring MVC๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด HTTP ํ—ค๋” ์ •๋ณด๋ฅผ ์ฝ์–ด์˜ค๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Œ

  1. @RequestHeader๋กœ ๊ฐœ๋ณ„ ํ—ค๋” ์ •๋ณด ๋ฐ›๊ธฐ

  2. @RequestHeader๋กœ ์ „์ฒด ํ—ค๋” ์ •๋ณด ๋ฐ›๊ธฐ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
     import com.codestates.section3.week1.api.mvc_examples.common.Member;
     import org.springframework.http.HttpStatus;
     import org.springframework.http.ResponseEntity;
     import org.springframework.web.bind.annotation.*;
        
     import java.util.Map;
        
     @RestController
     @RequestMapping(path = "/v1/members")
     public class MemberController {
         @PostMapping
         public ResponseEntity postMember(@RequestHeader Map<String, String> headers,//(1)
                                          @RequestParam("email") String email,
                                          @RequestParam("name") String name,
                                          @RequestParam("phone") String phone) {
             for (Map.Entry<String, String> entry : headers.entrySet()) {
                 System.out.println("key: " + entry.getKey() +
                         ", value: " + entry.getValue());
             }
        
             return new ResponseEntity<>(new Member(email, name, phone),
                     HttpStatus.CREATED);
         }
     }
        
     //์ถœ๋ ฅ๊ฒฐ๊ณผ
     key: user-agent, value: PostmanRuntime/7.29.0
     key: accept, value: */*
     key: cache-control, value: no-cache
     key: postman-token, value: 6082ccc2-3195-4726-84ed-6a2009cbae95
     key: host, value: localhost:8080
     key: accept-encoding, value: gzip, deflate, br
     key: connection, value: keep-alive
     key: content-type, value: application/x-www-form-urlencoded
     key: content-length, value: 54
        
    
  3. HttpServletRequest ๊ฐ์ฒด๋กœ ํ—ค๋”์ •๋ณด ์–ป๊ธฐ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
     @RestController
     @RequestMapping(path = "/v1/orders")
     public class OrderController {
         @PostMapping
         public ResponseEntity postOrder(HttpServletRequest httpServletRequest,//(1)
                                         @RequestParam("memberId") long memberId,
                                         @RequestParam("coffeeId") long coffeeId) {
             System.out.println("user-agent: " + httpServletRequest.getHeader("user-agent"));
        
             return new ResponseEntity<>(new Order(memberId, coffeeId),
                     HttpStatus.CREATED);
         }
     }
        
    
    • ์ž˜ ์•ˆ ์”€
    • ์ด ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ์ˆœ๊ฐ„ http์›นํ™˜๊ฒฝ์— ์ข…์†๋˜์–ด๋ฒ„๋ ค์„œ ๊ฐ€๋Šฅํ•œ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ
  4. HttpEntity ๊ฐ์ฒด๋กœ ํ—ค๋” ์ •๋ณด ์–ป๊ธฐ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
     @RestController
     @RequestMapping(path = "/v1/coffees")
     public class CoffeeController{
         @PostMapping
         public ResponseEntity postCoffee(@RequestHeader("user-agent") String userAgent,//(1)
                                          @RequestParam("korName") String korName,
                                          @RequestParam("engName") String engName,
                                          @RequestParam("price") int price) {
             System.out.println("user-agent: " + userAgent);
             return new ResponseEntity<>(new Coffee(korName, engName, price),
                     HttpStatus.CREATED);
         }
        
         @GetMapping
         public ResponseEntity getCoffees(**HttpEntity httpEntity**) {
             for(Map.Entry<String, List<String>> entry : httpEntity.getHeaders().entrySet()){
                 System.out.println("key: " + entry.getKey()
                         + ", " + "value: " + entry.getValue());
             }
        
             System.out.println("host: " + httpEntity.getHeaders().getHost());
             return null;
         }
     }
        
     //์ถœ๋ ฅ๊ฒฐ
     key: user-agent, value: [PostmanRuntime/7.29.0]
     key: accept, value: [*/*]
     key: cache-control, value: [no-cache]
     key: postman-token, value: [368ad61b-b196-4f75-9222-b9a5af750414]
     key: host, value: [localhost:8080]
     key: accept-encoding, value: [gzip, deflate, br]
     key: connection, value: [keep-alive]
     host: localhost:8080
    
    • HttpEntity๋Š” Request ํ—ค๋”์™€ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์กฐ๊ธˆ ๋” ์‰ฝ๊ฒŒ ํ—ค๋”์™€ ๋ฐ”๋””์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ API๋ฅผ ์ง€์›

HTTP Response ํ—ค๋” ์ •๋ณด ์ถ”๊ฐ€

  1. ResponseEntity์™€ HttpHeaders๋ฅผ ์ด์šฉํ•ด ํ—ค๋” ์ •๋ณด ์ถ”๊ฐ€

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     @RestController
     @RequestMapping(path = "/v1/members")
     public class MemberController{
         @PostMapping
         public ResponseEntity postMember(@RequestParam("email") String email,
                                          @RequestParam("name") String name,
                                          @RequestParam("phone") String phone) {
             // (1) ์œ„์น˜ ์ •๋ณด๋ฅผ ํ—ค๋”์— ์ถ”๊ฐ€
             HttpHeaders headers = new HttpHeaders();
             headers.set("Client-Geo-Location", "Korea,Seoul");
        
             return new ResponseEntity<>(new Member(email, name, phone), headers,
                     HttpStatus.CREATED);
         }
     }
    
    • HttpHeaders์˜ set() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ํ—ค๋” ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ
  2. HttpServletResponse ๊ฐ์ฒด๋กœ ํ—ค๋” ์ •๋ณด ์ถ”๊ฐ€

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     @RestController
     @RequestMapping(path = "/v1/members")
     public class MemberController{
         @GetMapping
         public ResponseEntity getMembers(HttpServletResponse response) {
             response.addHeader("Client-Geo-Location", "Korea,Seoul");
        
             return null;
         }
     }
        
    

    HttpServletRequest์™€ HttpServletResponse๋Š” ์ €์ˆ˜์ค€(Low Level)์˜ ์„œ๋ธ”๋ฆฟ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์žกํ•œ HTTP Request/Response๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๊ฐ€๋Šฅ

    ๋ฐ˜๋ฉด์— ResponseEntity๋‚˜ HttpHeaders๋Š” Spring์—์„œ ์ง€์›ํ•˜๋Š” ๊ณ ์ˆ˜์ค€(High Level) API๋กœ์จ ๊ฐ„๋‹จํ•œ HTTP Request/Response ์ฒ˜๋ฆฌ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ง„ํ–‰๊ฐ€๋Šฅ

    ๋ณต์žกํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐ์„ฑ์ด๋‚˜ ์ƒ์‚ฐ์„ฑ ๋ฉด์—์„œ ๊ฐ€๊ธ‰์  Spring์—์„œ ์ง€์›ํ•˜๋Š” ๊ณ ์ˆ˜์ค€ API๋ฅผ ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒ์žฅ

Rest Client

ํด๋ผ์ด์–ธํŠธ(Client)์™€ ์„œ๋ฒ„(Server)์˜ ๊ด€๊ณ„

โ€‹

  1. ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์›น ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ HTML ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณต๋ฐ›๋Š” ํด๋ผ์ด์–ธํŠธ

    ์ฆ‰, ์„œ๋ฒ„ ์ชฝ์˜ ๋ฆฌ์†Œ์Šค(Resource, ์ž์›)๋ฅผ ์ด์šฉํ•˜๋Š” ์ธก์ด ํด๋ผ์ด์–ธํŠธ

  2. ์„œ๋ฒ„๋„ ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์Œ

    โ‡’ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ : Frontend ์„œ๋ฒ„์™€ Backend ์„œ๋ฒ„์˜ ๊ด€๊ณ„

    ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์˜ ๊ด€๊ณ„๋Š” ์ƒ๋Œ€์ 

    • ๋ธŒ๋ผ์šฐ์ € ์ž…์žฅ์—์„œ๋Š” Frontend์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ช…๋ฐฑํ•œ ํด๋ผ์ด์–ธํŠธ
    • Frontend๊ฐ€ Backend์— ๋™์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋จ
  3. ๋ฐฑ์—”๋“œ ์„œ๋ฒ„
    • Backend ์„œ๋ฒ„ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค๋ฅธ ์„œ๋ฒ„์—๊ฒŒ HTTP ์š”์ฒญ์„ ์ „์†กํ•ด์„œ ์ž‘์—…์„ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์Œ.
    • backend A๊ฐ€ Frontend์—๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„ ์—ญํ• ์„ ํ•˜์ง€๋งŒ Backend A์—์„œ Backend B์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋‹ค์‹œ ์ด์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— Backend B์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด์šฉํ•  ๋•Œ๋Š” Backend A๋„ ํด๋ผ์ด์–ธํŠธ์˜ ์—ญํ• ์„ ํ•˜๊ฒŒ ๋จ.
  4. ์–ด๋–ค ์„œ๋ฒ„๊ฐ€ HTTP ํ†ต์‹ ์„ ํ†ตํ•ด์„œ ๋‹ค๋ฅธ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ๊ทธ๋•Œ๋งŒํผ์€ ํด๋ผ์ด์–ธํŠธ์˜ ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๊ธฐ

Rest Client๋ž€?

  • Rest API ์„œ๋ฒ„์— HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ ํˆด ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์˜๋ฏธ
  • Postman์€ UI๊ฐ€ ๊ฐ–์ถฐ์ง„ Rest Client๋ผ ๋ณผ ์ˆ˜ ์žˆ์Œ
  • RestTemplate
    • Spring์—์„œ ์ œ๊ณตํ•˜๋Š” RestClient API
    • HTTP Client ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ด์šฉํ•ด์„œ ์›๊ฒฉ์ง€์— ์žˆ๋Š” ๋‹ค๋ฅธ Backend ์„œ๋ฒ„์— HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Œ
    • Rest ์—”๋“œ ํฌ์ธํŠธ ์ง€์ •, ํ—ค๋” ์„ค์ •, ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ body ์„ค์ •์„ ํ•œ ์ค„์˜ ์ฝ”๋“œ๋กœ ์†์‰ฝ๊ฒŒ ์ „์†ก ๊ฐ€๋Šฅ
    • java.net.HttpURLConnection, Apache HttpComponents, OkHttp 3, Netty ๊ฐ™์€ HTTP Client ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Rest Template

  1. ๊ฐ์ฒด ์ƒ์„ฑ

    1
    2
    3
    4
    5
    6
    7
    8
    
     public class RestClientExample01 {
         public static void main(String[] args) {
             // (1) ๊ฐ์ฒด ์ƒ์„ฑ
             RestTemplate restTemplate =
                     new RestTemplate(new HttpComponentsClientHttpRequestFactory());
         }
     }
        
    
    • RestTemplate์˜ ์ƒ์„ฑ์ž ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ HTTP Client ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ
    • HttpComponentsClientHttpRequestFactory ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด Apache HttpComponents๋ฅผ ์ „๋‹ฌ
      • Apache HttpComponents๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” builde.gradle์˜ dependencies ํ•ญ๋ชฉ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์˜์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•จ
      1
      2
      3
      4
      5
      6
      
        dependencies {
            ...
            ...
            implementation 'org.apache.httpcomponents:httpclient'
        }
              
      
  2. URI ์ƒ์„ฑ

    ๊ฐ์ฒด ์ƒ์„ฑ ๋˜์—ˆ๋‹ค๋ฉด HTTP Request๋ฅผ ์ „์†กํ•  Rest ์—”๋“œํฌ์ธํŠธ์˜ URI๋ฅผ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ํ•จ

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
     import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
     import org.springframework.web.client.RestTemplate;
     import org.springframework.web.util.UriComponents;
     import org.springframework.web.util.UriComponentsBuilder;
        
     import java.net.URI;
        
     public class RestClientExample01 {
         public static void main(String[] args) {
             // (1) ๊ฐ์ฒด ์ƒ์„ฑ
             RestTemplate restTemplate =
                     new RestTemplate(new HttpComponentsClientHttpRequestFactory());
        
             // (2) URI ์ƒ์„ฑ
             UriComponents uriComponents =
                     UriComponentsBuilder
                             .newInstance()
                             .scheme("http")
                             .host("worldtimeapi.org")
     //                        .port(80)
                             .path("/api/timezone/{continents}/{city}")
                             .encode()
                             .build();
             URI uri = uriComponents.expand("Asia", "Seoul").toUri();
         }
     }
        
    
    • UriComponentsBuilder ํด๋ž˜์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” API ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ
      • newInstance()
        • UriComponentsBuilder ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
      • scheme()
        • URI์˜ scheme์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
      • host()
        • ํ˜ธ์ŠคํŠธ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
      • port()
        • ๋””ํดํŠธ ๊ฐ’์€ 80์ด๋ฏ€๋กœ 80 ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ˜ธ์ŠคํŠธ๋ผ๋ฉด ์ƒ๋žต ๊ฐ€๋Šฅ
      • path()
        • URI์˜ ๊ฒฝ๋กœ(path)๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
        • [์ฝ”๋“œ 3-18]์—์„œ๋Š” URI์˜ path์—์„œ {continents}, {city}์˜ ๋‘ ๊ฐœ์˜ ํ…œํ”Œ๋ฆฟ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ
        • ๋‘ ๊ฐœ์˜ ํ…œํ”Œ๋ฆฟ ๋ณ€์ˆ˜๋Š” uriComponents.expand("Asia", "Seoul").toUri();์—์„œ expand() ๋ฉ”์„œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๋ฌธ์ž์—ด๋กœ ์ฑ„์›Œ์ง
        • ์ฆ‰, ๋นŒ๋“œ ํƒ€์ž„์— {continents}๋Š” โ€˜Asiaโ€™, {city}๋Š” โ€˜Seoulโ€™๋กœ ๋ณ€ํ™˜๋จ
      • encode()
        • URI์— ์‚ฌ์šฉ๋œ ํ…œํ”Œ๋ฆฟ ๋ณ€์ˆ˜๋“ค์„ ์ธ์ฝ”๋”ฉํ•ด์ค๋‹ˆ๋‹ค.
        • ์—ฌ๊ธฐ์„œ ์ธ์ฝ”๋”ฉ์˜ ์˜๋ฏธ๋Š” non-ASCII ๋ฌธ์ž์™€ URI์— ์ ์ ˆํ•˜์ง€ ์•Š์€ ๋ฌธ์ž๋ฅผ Percent Encoding ํ•œ๋‹ค๋Š” ์˜๋ฏธ
      • build()
        • UriComponents ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
    • UriComponents์— ์‚ฌ์šฉ๋œ API ๋ฉ”์„œ๋“œ
      • expand()
        • ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ž…๋ ฅํ•œ ๊ฐ’์„ URI ํ…œํ”Œ๋ฆฟ ๋ณ€์ˆ˜์˜ ๊ฐ’์œผ๋กœ ๋Œ€์ฒด
      • toUri()
        • URI ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
  3. ์š”์ฒญ ์ „์†ก

    1. getForObject()๋ฅผ ์ด์šฉํ•œ ๋ฌธ์ž์—ด ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ „๋‹ฌ๋ฐ›๊ธฐ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      
      public class RestClientExample01 {
          public static void main(String[] args) {
              // (1) ๊ฐ์ฒด ์ƒ์„ฑ
              RestTemplate restTemplate =
                      new RestTemplate(new HttpComponentsClientHttpRequestFactory());
             
              // (2) URI ์ƒ์„ฑ
              UriComponents uriComponents =
                      UriComponentsBuilder
                              .newInstance()
                              .scheme("http")
                              .host("worldtimeapi.org")
      //                        .port(80)
                              .path("/api/timezone/{continents}/{city}")
                              .encode()
                              .build();
              URI uri = uriComponents.expand("Asia", "Seoul").toUri();
             
              // (3) Request ์ „์†ก
              String result = restTemplate.getForObject(uri, String.class);
             
              System.out.println(result);
          }
      }
             
      

      getForObject(URI uri, Class<T> responseType)

      • ๊ธฐ๋Šฅ ์„ค๋ช…

        • getForObject() ๋ฉ”์„œ๋“œ๋Š” HTTP Get ์š”์ฒญ์„ ํ†ตํ•ด ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์กฐํšŒ
      • ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช…

        • URI uri
          • Request๋ฅผ ์ „์†กํ•  ์—”๋“œํฌ์ธํŠธ์˜ URI ๊ฐ์ฒด๋ฅผ ์ง€์ •
        • Class<T> responseType
          • ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ๋ฐ›์„ ํด๋ž˜์Šค์˜ ํƒ€์ž…์„ ์ง€์ •
          • ์ฝ”๋“œ 3-19์—์„œ๋Š” ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก String.class๋กœ ์ง€์ •
      • ์‹คํ–‰๊ฒฐ๊ณผ

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        
        abbreviation: KST
        client_ip: 125.129.191.130
        datetime: 2022-04-28T09:49:44.492621+09:00
        day_of_week: 4
        day_of_year: 118
        dst: false
        dst_from:
        dst_offset: 0
        dst_until:
        raw_offset: 32400
        timezone: Asia/Seoul
        unixtime: 1651106984
        utc_datetime: 2022-04-28T00:49:44.492621+00:00
        utc_offset: +09:00
        week_number: 17
                 
        
    2. getForObject()๋ฅผ ์ด์šฉํ•œ ์ปค์Šคํ…€ ํด๋ž˜์Šค ํƒ€์ž…์œผ๋กœ ์›ํ•˜๋Š” ์ •๋ณด๋งŒ ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ๋ฐ›๊ธฐ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      
      public class RestClientExample02 {
          public static void main(String[] args) {
              // (1) ๊ฐ์ฒด ์ƒ์„ฑ
              RestTemplate restTemplate =
                      new RestTemplate(new HttpComponentsClientHttpRequestFactory());
             
              // (2) URI ์ƒ์„ฑ
              UriComponents uriComponents =
                      UriComponentsBuilder
                              .newInstance()
                              .scheme("http")
                              .host("worldtimeapi.org")
      //                        .port(80)
                              .path("/api/timezone/{continents}/{city}")
                              .encode()
                              .build();
              URI uri = uriComponents.expand("Asia", "Seoul").toUri();
             
              // (3) Request ์ „์†ก. WorldTime ํด๋ž˜์Šค๋กœ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค.
              WorldTime worldTime = restTemplate.getForObject(uri, WorldTime.class);
             
              System.out.println("# datatime: " + worldTime.getDatetime());
              System.out.println("# timezone: " + worldTime.getTimezone());
              System.out.println("# day_of_week: " + worldTime.getDay_of_week());
          }
      }
             
      

      [์‘๋‹ต๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ ์œ„ํ•œ WorldTime ํด๋ž˜์Šค]

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
      public class WorldTime {
          private String datetime;
          private String timezone;
          private int day_of_week;
             
          public String getDatetime() {
              return datetime;
          }
             
          public String getTimezone() {
              return timezone;
          }
             
          public int getDay_of_week() {
              return day_of_week;
          }
      }
             
      

      [์‹คํ–‰๊ฒฐ๊ณผ]

      1
      2
      3
      
      # datatime: 2021-10-10T11:39:15.099207+09:00
      # timezone: Asia/Seoul
      # day_of_week: 4
      
    3. getForEntity()๋ฅผ ์‚ฌ์šฉํ•œ Response Body(๋ฐ”๋””, ์ฝ˜ํ…์ธ ) + Header(ํ—ค๋”) ์ •๋ณด ์ „๋‹ฌ๋ฐ›๊ธฐ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      
      public class RestClientExample02 {
          public static void main(String[] args) {
              // (1) ๊ฐ์ฒด ์ƒ์„ฑ
              RestTemplate restTemplate =
                      new RestTemplate(new HttpComponentsClientHttpRequestFactory());
             
              // (2) URI ์ƒ์„ฑ
              UriComponents uriComponents =
                      UriComponentsBuilder
                              .newInstance()
                              .scheme("http")
                              .host("worldtimeapi.org")
      //                        .port(80)
                              .path("/api/timezone/{continents}/{city}")
                              .encode()
                              .build();
              URI uri = uriComponents.expand("Asia", "Seoul").toUri();
             
              // (3) Request ์ „์†ก. ResponseEntity๋กœ ํ—ค๋”์™€ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
              ResponseEntity<WorldTime> response =
                      restTemplate.getForEntity(uri, WorldTime.class);
             
              System.out.println("# datatime: " + response.getBody().getDatetime());
              System.out.println("# timezone: " + response.getBody().getTimezone()());
              System.out.println("# day_of_week: " + response.getBody().getDay_of_week());
              System.out.println("# HTTP Status Code: " + response.getStatusCode());
              System.out.println("# HTTP Status Value: " + response.getStatusCodeValue());
              System.out.println("# Content Type: " + response.getHeaders().getContentType());
              System.out.println(response.getHeaders().entrySet());
          }
      }
      

      getForEntity() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ—ค๋” ์ •๋ณด์™€ ๋ฐ”๋”” ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ „๋‹ฌ๋ฐ›๊ณ ์žˆ์Œ

    4. exchange()๋ฅผ ์‚ฌ์šฉํ•œ ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ฐ›๊ธฐ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      
      public class RestClientExample03 {
          public static void main(String[] args) {
              // (1) ๊ฐ์ฒด ์ƒ์„ฑ
              RestTemplate restTemplate =
                      new RestTemplate(new HttpComponentsClientHttpRequestFactory());
             
              // (2) URI ์ƒ์„ฑ
              UriComponents uriComponents =
                      UriComponentsBuilder
                              .newInstance()
                              .scheme("http")
                              .host("worldtimeapi.org")
      //                        .port(80)
                              .path("/api/timezone/{continents}/{city}")
                              .encode()
                              .build();
              URI uri = uriComponents.expand("Asia", "Seoul").toUri();
             
              // (3) Request ์ „์†ก. exchange()๋ฅผ ์‚ฌ์šฉํ•œ ์ผ๋ฐ˜ํ™” ๋œ ๋ฐฉ์‹
              ResponseEntity<WorldTime> response =
                      restTemplate.exchange(uri,
                              HttpMethod.GET,
                              null,
                              WorldTime.class);
             
              System.out.println("# datatime: " + response.getBody().getDatetime());
              System.out.println("# timezone: " + response.getBody().getTimezone());
              System.out.println("# day_of_week: " + response.getBody().getDay_of_week());
              System.out.println("# HTTP Status Code: " + response.getStatusCode());
              System.out.println("# HTTP Status Value: " + response.getStatusCodeValue());
          }
      }
             
      

      exchange(URI uri, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType)

      • ๊ธฐ๋Šฅ ์„ค๋ช…
        • getForObject(), getForEntity() ๋“ฑ๊ณผ ๋‹ฌ๋ฆฌ exchange() ๋ฉ”์„œ๋“œ๋Š” HTTP Method, RequestEntity, ResponseEntity๋ฅผ ์ง์ ‘ ์ง€์ •ํ•ด์„œ HTTP Request๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹
      • ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช…
        • URI url
          • Request๋ฅผ ์ „์†กํ•  ์—”๋“œํฌ์ธํŠธ์˜ URI ๊ฐ์ฒด๋ฅผ ์ง€์ •
        • HttpMethod method
          • HTTP Method ํƒ€์ž…์„ ์ง€์ •
        • HttpEntity<?> requestEntity
          • HttpEntity ๊ฐ์ฒด๋ฅผ ์ง€์ •
          • HttpEntity ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ—ค๋” ๋ฐ ๋ฐ”๋””, ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ์„ ์„ค์ •๊ฐ€๋Šฅ
        • Class<T> responseType
          • ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ๋ฐ›์„ ํด๋ž˜์Šค์˜ ํƒ€์ž…์„ ์ง€์ •


### comment

๋ฐฐ์šด๋“ฏ ์•ˆ๋ฐฐ์šด๋“ฏ ์ƒ์†Œํ•œ ๋А๋‚Œ, ์ด๊ฑฐ ์•„๋Š”๋ฐ ์‹ถ๋‹ค๊ฐ€๋„ ๋ชจ๋ฅด๊ฒ ๋‹คโ€ฆ








๐Ÿ’ ๊ณต์ง€

- ์ •๋ณด ๊ณต์œ ๊ฐ€ ์•„๋‹Œ ๊ฐœ์ธ ๊ณต๋ถ€ ๊ธฐ๋ก์šฉ์ž…๋‹ˆ๋‹ค.

Spring ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment