[7/5 TIL] SPRING MVC(WebApplicationContext, REST(ful) API)

yumyeonghanยท2023๋…„ 7์›” 6์ผ
0

๐Ÿƒํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐฑ์—”๋“œ ๋ฐ๋ธŒ์ฝ”์Šค 4๊ธฐ ๊ต์œก๊ณผ์ •์„ ๋“ฃ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.๐Ÿƒ

WebApplicationContext

  • Spring Framework์—์„œ ์ œ๊ณตํ•˜๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ApplicationContext์˜ ๊ตฌํ˜„์ฒด
  • ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ์—์„œ Spring์˜ IoC ์ปจํ…Œ์ด๋„ˆ์™€ DI(Dependency Injection) ๊ธฐ๋Šฅ์„ ์ œ๊ณต
  • ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ๋นˆ(Bean)๋“ค์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌ
  • ์›น ์‹คํ–‰์‹œ, ContextLoaderListener๊ฐ€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ServletContext์— ์ €์žฅ
  • ContextLoaderListener๋ฅผ ํ†ตํ•ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ํŽธ์˜์ƒ servlet applicationContext๋ผ๊ณ  ํ•จ

ServletContext

๊ทธ๋ฆผ ์ถœ์ฒ˜

  • ์—ฌ๋Ÿฌ ์„œ๋ธ”๋ฆฟ์˜ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ์ผ์ข…์˜ ๊ฐ์ฒด
  • Dispatcher Servlet์„ ํฌํ•จํ•œ ์—ฌ๋Ÿฌ ์„œ๋ธ”๋ฆฟ์—์„œ ์ ‘๊ทผํ•˜์—ฌ ๊ณต์šฉ ์ž์›์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋จ
  • ๊ฐ ์„œ๋ธ”๋ฆฟ์€ ํ•„์š”์— ๋”ฐ๋ผ WebApplicationContext์—์„œ ํ•„์š”ํ•œ ๋นˆ(Bean)๋“ค์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉ

ContextLoaderListener

  • ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹น
  • ContextLoaderListener๋Š” ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ servlet applicationContext์— ์ €์žฅ
  • ContextLoaderListener๋ฅผ ํ†ตํ•ด ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ํŽธ์˜์ƒ root applicationContext๋ผ๊ณ  ํ•จ

๋™์ž‘ ๋ฐฉ์‹

๊ทธ๋ฆผ ์ถœ์ฒ˜

  • Dispatcher Servlet์€ ์—ฌ๋Ÿฌ๊ฐœ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ๊ณ , ์ปจํŠธ๋กค๋Ÿฌ๋Š” ํ•ด๋‹น Dispatcher Servlet์— ๋งคํ•‘ ๋จ
  • Dispatcher Servlet์ด ์‚ฌ์šฉํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋Š” ์›น ์‹คํ–‰์‹œ, ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” servlet applicationContext์— ๋“ฑ๋ก๋œ ๋นˆ๋“ค
  • ์„œ๋น„์Šค์™€ DAO์˜์—ญ์€ ์›น ์‹คํ–‰์‹œ, ์ˆ˜๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” root applicationContext์— ๋“ฑ๋ก๋œ ๋นˆ๋“ค
  • ์œ„์™€ ๊ฐ™์ด ๊ณ„์ธต ๋ณ„๋กœ ๋‚˜๋ˆŒ์ˆ˜๋„ ์žˆ๊ณ , ํ•˜๋‚˜์˜ IOC ์ปจํ…Œ์ด๋„ˆ(์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ)์— ๋ชจ๋“  ๋นˆ๋“ค์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Œ

REST(ful) API

REST ์•„ํ‚คํ…์ณ ์Šคํƒ€์ผ์„ ๋”ฐ๋ฅด๋Š” API

Rest ์•„ํ‚คํ…์ณ ์Šคํƒ€์ผ

  • ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ (client-server)
    • ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ๊ด€์‹ฌ์„ ๋ฐ์ดํ„ฐ ์ €์žฅ์— ๋Œ€ํ•œ ๊ด€์‹ฌ์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ํด๋ผ์ด์–ธํŠธ์˜ ์ด์‹์„ฑ๊ณผ ์„œ๋ฒ„์˜ ๊ทœ๋ชจ ํ™•์žฅ์„ฑ์„ ๊ฐœ์„ 
  • ์Šคํ…Œ์ดํŠธ๋ฆฌ์Šค (stateless)
    • ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„์˜ ํ†ต์‹ ์— ์ƒํƒœ๊ฐ€ ์—†์Œ
    • ๋ชจ๋“  ์š”์ฒญ์—๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ์–ด ๊ฐ€์‹œ์„ฑ์ด ์ข‹๊ณ  ์š”์ฒญ ์‹คํŒจ์‹œ ๋ณต์›์ด ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์‹ ๋ขฐ์„ฑ์ด ์ข‹์Œ
    • ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์—†์–ด ๊ทœ๋ชจํ™•์žฅ์„ฑ์ด ๊ฐœ์„ 
  • ์บ์‹œ (cache)
    • ์บ์‹œ๊ฐ€ ๊ฐ€๋Šฅํ•ด์•ผ ํ•˜๊ณ , HTTP๊ฐ€ ๊ฐ€์ง„ ์บ์‹ฑ ๊ธฐ๋Šฅ์ด ์ ์šฉ ๊ฐ€๋Šฅ
    • HTTP ํ”„๋กœํ† ์ฝœ ํ‘œ์ค€์—์„œ ์‚ฌ์šฉํ•˜๋Š” Last-Modifiedํƒœ๊ทธ๋‚˜ E-Tag๋ฅผ ์ด์šฉํ•˜๋ฉด ์บ์‹ฑ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅ
  • ๊ท ์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค (uniform interface)
    • URI๋กœ ์ง€์ •ํ•œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์กฐ์ž‘์„ ํ†ต์ผ๋˜๊ณ  ํ•œ์ •์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ
  • ๊ณ„์ธตํ™”๋œ ์‹œ์Šคํ…œ (layered system)
    • REST ์„œ๋ฒ„๋Š” ๋‹ค์ค‘ ๊ณ„์ธต์œผ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ์Œ
    • ๋ณด์•ˆ, ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ, ์•”ํ˜ธํ™” ๊ณ„์ธต์„ ์ถ”๊ฐ€ํ•ด ๊ตฌ์กฐ์ƒ์˜ ์œ ์—ฐ์„ฑ์„ ๋‘˜ ์ˆ˜ ์žˆ๊ณ  PROXY, ๊ฒŒ์ดํŠธ์›จ์ด ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ๊ธฐ๋ฐ˜์˜ ์ค‘๊ฐ„๋งค์ฒด๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

REST ์•„ํ‚คํ…์ณ ์Šคํƒ€์ผ Level

๊ทธ๋ฆผ ์ถœ์ฒ˜

Level 3๊นŒ์ง€ ์ ์šฉํ•˜๋ฉด, REST ์•„ํ‚คํ…์ณ ์Šคํƒ€์ผ์— ๊ฐ€์žฅ ๊ทผ์ ‘ํ•˜๊ฒŒ API๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ๋ด„

  • Level 0
    • ๊ฐ€์žฅ ํ•˜์œ„์˜ ๋ ˆ๋ฒจ
    • HTTP๋ฅผ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค๋ฅผ ์ „๋‹ฌํ–ˆ๋‹ค๋ผ๋Š” ์˜์˜
    • REST๋Š” ์•„๋‹˜
  • Level 1
    • Resources ์ถ”๊ฐ€
    • ๋ฆฌ์†Œ์Šค์˜ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ๋Š” ์ •๋ณด์ด๊ณ  representation data์™€ representation metadata๋กœ ๊ตฌ์„ฑ
      ๊ทธ๋ฆผ ์ถœ์ฒ˜
  • Level 2
    • HTTP ๋ฉ”์„œ๋“œ ๋„์ž…
  • Level 3
    • HATEOAS
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‘๋‹ต ๋ฐ›์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ–๊ณ  ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‘๋‹ต ๋ฉ”์„ธ์ง€์— ์•Œ๋ ค์คŒ
      ๊ทธ๋ฆผ ์ถœ์ฒ˜

API ์„ค๊ณ„

GET /members/delete/1	//์‚ฌ์šฉ x
DELETE /members/1		//์‚ฌ์šฉ o
GET /members/show/1		//์‚ฌ์šฉ x
GET /members/1			//์‚ฌ์šฉ o
POST /task/1/run		//์‚ฌ์šฉ o
  • URI๋Š” ์ •๋ณด์˜ ์ž์›์„ ํ‘œํ˜„ํ•ด์•ผ ํ•˜๊ณ , ๋ฆฌ์†Œ์Šค๋ช…์€ ๋™์‚ฌ๋ณด๋‹ค ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉ
  • ์ž์›์— ๋Œ€ํ•œ ํ–‰์œ„๋Š” ๋™์‚ฌ ๋Œ€์‹  HTTP Method๋กœ ํ‘œํ˜„
  • ์Šฌ๋ž˜์‹œ ๊ตฌ๋ถ„์ž(/)๋Š” ๊ณ„์ธต ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ
  • URI ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋กœ ์Šฌ๋ž˜์‹œ(/) ํฌํ•จ ์•ˆํ•จ
  • ๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ํ•˜์ดํฐ(-) ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • CRUD๊ฐ€ ์•„๋‹Œ, ํŠน์ • ํ–‰์œ„๋ฅผ ํ‘œํ˜„ํ•˜๋ ค๋ฉด URI์˜ ๋งˆ์ง€๋ง‰์— ๋™์‚ฌ ํ‘œํ˜„

์Šคํ”„๋ง์—์„œ REST API ์‚ฌ์šฉ

  • @RequestBody: ์ „๋‹ฌ๋ฐ›์€ ์š”์ฒญ ๋ฉ”์„ธ์ง€๋ฅผ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
    // ํด๋ผ์ด์–ธํŠธ์—์„œ ์ „์†กํ•œ JSON ๋˜๋Š” XML ๋ฐ์ดํ„ฐ๋ฅผ User ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ›์Œ
    // User ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ํ•„์š”ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰
    // ...

    // ์ƒ์„ฑ๋œ User ๊ฐ์ฒด๋ฅผ HTTP ์‘๋‹ต์˜ ๋ณธ๋ฌธ์œผ๋กœ ๋ฐ˜ํ™˜
    return ResponseEntity.ok(user);
}

  • @ResponseBody: ์ •์˜ํ•œ ๋ชจ๋ธ ํด๋ž˜์Šค๋ฅผ ResponseBody ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
@GetMapping("/users/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
    // id์— ํ•ด๋‹นํ•˜๋Š” User ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒ
    // ...

    // ์กฐํšŒ๋œ User ๊ฐ์ฒด๋ฅผ HTTP ์‘๋‹ต์˜ ๋ณธ๋ฌธ์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†ก
    return user;
}

  • @RestController: ํด๋ž˜์Šค์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์— @ResponseBody ์ ์šฉ
@RestController // @Controller + @ResponseBody
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        // ...
    }

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        // ...
    }
}

HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ

๊ทธ๋ฆผ ์ถœ์ฒ˜

  • Spring MVC์—์„œ HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ๋ณธ๋ฌธ(body)์„ ์ž๋ฐ” ๊ฐ์ฒด์™€ HTTP ๋ฉ”์‹œ์ง€ ํ˜•์‹(JSON, XML, TEXT ๋“ฑ) ๊ฐ„์— ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ JSON ํ˜•์‹์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋Š” JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜
  • ์„œ๋ฒ„๊ฐ€ JSON ํ˜•์‹์œผ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ด๋ฉด ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ „์†ก
  • ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์˜ Content-Type ํ—ค๋”์™€ ์„œ๋ฒ„ ์‘๋‹ต์˜ Accept ํ—ค๋”๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ ์ ˆํ•œ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์„ ํƒ
  • Spring MVC๋Š” ๋‹ค์–‘ํ•œ ํ˜•์‹์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ HTTP ๋ฉ”์‹œ์ง€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ์šฐ์„ ์ˆœ์œ„ ๋ถ€์—ฌ ๊ฐ€๋Šฅ

Http Client ๋„๊ตฌ

  • Intellij HTTP Client
  • Postman
profile
์›น ๊ฐœ๋ฐœ์— ๊ด€์‹ฌ ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€