RestApi ๋งŒ๋“ค๊ธฐ - ์ด๋ฒคํŠธ ์กฐํšŒ API๊ตฌํ˜„ (10)

๋ฐ˜์‘ํ˜•

๊ณง ํšŒ์‚ฌ์ผ์ด ๋ฐ”๋น ์ง„๋‹ค๊ณ  ํ•œ๋‹ค.
๋ฐ”๋น ์ง€๊ธฐ ์ „์— ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ํ•˜์ž!

๊ฐ„๋‹จํ•˜๊ฒŒ ํ…Œ์ŠคํŠธ ๋ถ€ํ„ฐ ์ž‘์„ฑํ•ด๋ณด์ž.

@Test
  public void create_event() throws Exception {
    Delivery delivery = generateEvent(100);
    this.mockMvc.perform(get("/api/delivery/{id}",delivery.getId()))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("id").exists())
                .andExpect(jsonPath("_links.self").exists())
                .andExpect(jsonPath("_links.profile").exists());
  }

์ด๊ฒƒ์„ ์‹คํ–‰ํ•˜๋ฉด
์–ด๋–ค ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ?

์™œ 404๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ?
์™œ๋ƒํ•˜๋ฉด...
controller์— ๋งŒ๋“ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ์ „์— ๋งŒ์•ฝ์— ์ž˜๋ชป๋œ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

@Test
  public void create_event_bad() throws Exception {
    this.mockMvc.perform(get("/api/delivery/9999999"))
        .andDo(print())
        .andExpect(status().isNotFound())
        .andExpect(jsonPath("id").exists())
        .andExpect(jsonPath("_links.self").exists())
        .andExpect(jsonPath("_links.profile").exists());
  }

๊ทธ๋Ÿฌ๋ฉด ์ด๊ฑฐ๋Š” ์„ฑ๊ณตํ• ๊นŒ?
์‚ฌ์‹ค..์ด๊ฒƒ๋„ ์‹คํŒจํ•œ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
controller๋ฅผ ๋งŒ๋“ค์ž.

@GetMapping("/{id}")
  public ResponseEntity<?> getEvent(@PathVariable Integer id) {
    Optional<Delivery> delivery = deliveryRepository.findById(id);
    if (delivery.isEmpty()) {
      return ResponseEntity.notFound().build();
    }
        
    return ResponseEntity.ok(delivery);
}

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด ๋ ๊นŒ?
์• ์„ํ•˜๊ฒŒ๋„ ์ด๊ฑด ์ •๋‹ต์ด ์•„๋‹ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค์ž.

@GetMapping("/{id}")
  public ResponseEntity<?> getEvent(@PathVariable Integer id) {
    Optional<Delivery> optionalDelivery = deliveryRepository.findById(id);
    if (optionalDelivery.isEmpty()) {
      return ResponseEntity.notFound().build();
    }
    Delivery delivery = optionalDelivery.get();
    EntityModel<Delivery> deliveryModel = DeliveryModel.modelOf(delivery);
    return ResponseEntity.ok(deliveryModel);
  }

์ƒ๊ฐํ•ด๋ณด๋‹ˆ 

public class DeliveryModel extends EntityModel<Delivery> {

  public static EntityModel<Delivery> modelOf(Delivery delivery) {
    EntityModel<Delivery> deliveryModel = EntityModel.of(delivery);
    deliveryModel.add(linkTo(DeliveryController.class).withRel("query-events"));
    deliveryModel.add(linkTo(DeliveryController.class).slash(delivery.getId()).withRel("update-events"));
    deliveryModel.add(linkTo(DeliveryController.class).slash(delivery.getId()).withSelfRel());
    return deliveryModel;
  }
}

์ด๊ณณ์—์„œ profile์€ ๋นผ์ค˜์•ผ ๋œ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ์—ฌ๊ธฐ์— ์กด์žฌํ•˜๋Š” ๋งํฌ๋“ค์€ ๊ธ€๋กœ๋ฒŒ?๋งํฌ์ด๊ธฐ ๋•Œ๋ฌธ์—...
๋นผ์ฃผ๋Š”๊ฒŒ ๋งž๋Š”๊ฒƒ ๊ฐ™๋‹ค.
๊ทธ๋Ÿฌ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ๋งŽ์ด ๊นจ์งˆ๊ฒƒ ๊ฐ™์€๋””ใ…œใ…œ
์•„๋ฌดํŠผ
์ด๊ฒƒ์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด

_links.profile์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋‚˜์˜จ๋‹ค.
๋งํฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์ž.
์ด์ œ ํ”„๋กœํŒŒ์ผ์ด ๋ญ”์ง€ ์•Œ๊ฒƒ ๊ฐ™๋‹ค.

์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“  ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋Š” ๋งˆ์ณค๋‹ค.

์ด์ œ docs๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.
์ด ๋ถ€๋ถ„์€ request๋ถ€๋ถ„์€ url๋งŒ ์กด์žฌํ•˜๊ตฌ
๋‚˜๋จธ์ง€๋Š” ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ๋ ๊ฒƒ ๊ฐ™๋‹ค.

@Test
  public void create_event() throws Exception {
    Delivery delivery = generateEvent(10);
    this.mockMvc.perform(get("/api/delivery/{id}", delivery.getId()))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(jsonPath("id").exists())
        .andExpect(jsonPath("_links.self").exists())
        .andExpect(jsonPath("_links.profile").exists())
        .andDo(document("get-event",
            links(linkWithRel("query-events").description("์ด๋ฒคํŠธ ์ƒ์„ฑ"),
                linkWithRel("update-events").description("์ด๋ฒคํŠธ ์ˆ˜์ •"),
                linkWithRel("self").description("ํ•ด๋‹น ์ด๋ฒคํŠธ๋กœ ์ด๋™"),
                linkWithRel("profile").description("ํ•ด๋‹น ์ด๋ฒคํŠธ๋กœ ์ด๋™")),
            responseHeaders(headerWithName(HttpHeaders.CONTENT_TYPE).description("ํ˜„์žฌ contentType")),
            responseFields(fieldWithPath("id").description("ํ˜„์žฌ ์ด๋ฒคํŠธ ์•„์ด๋””"),
                fieldWithPath("item").description("์ƒํ’ˆ๋ช…"),
                fieldWithPath("user").description("ํŒ๋งค์ž"),
                fieldWithPath("deliveryTime").description("์ถœ๋ฐœ ์‹œ๊ฐ„"),
                fieldWithPath("deliveryEndTime").description("๋„์ฐฉ ์‹œ๊ฐ„"),
                fieldWithPath("status").description("๋ฒ ์†ก ์ƒํƒœ"),
                fieldWithPath("itemPrice").description("๋ฌผํ’ˆ ๊ฐ€๊ฒฉ"),
                fieldWithPath("deliveryCost").description("๋ฐฐ์†ก๊ฐ€๊ฒฉ"),
                fieldWithPath("_links.query-events.href").description("์ด๋ฒคํŠธ ๋งํฌ๋กœ ๊ฐ€๊ธฐ"),
                fieldWithPath("_links.update-events.href").description("์ด๋ฒคํŠธ ์ˆ˜์ • ๋งํฌ ์ด๋™"),
                fieldWithPath("_links.self.href").description("ํ•ด๋‹น ๋งํฌ๋กœ ์ด๋™ํ•˜๊ธฐ"),
                fieldWithPath("_links.profile.href").description("์ด๋ฒคํŠธ ํ”„๋กœํŒŒ์ผ ๋งํฌ์ด๋™ํ•˜๊ธฐ"))));
  }

์ด๊ฑฐ๋Š” ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š์•˜๋‹ค.;;
์™„์„ฑํ’ˆ

๋Œ“๊ธ€

Designed by JB FACTORY