Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1단계 - 상품 관리 기능] 망고(고재철) 미션 제출합니다. #185

Merged
merged 41 commits into from
May 1, 2023

Conversation

Go-Jaecheol
Copy link

@Go-Jaecheol Go-Jaecheol commented Apr 26, 2023

안녕하세요 디디!
첫 번째 미션 이후로 다시 만났네요ㅎㅎ
이번에도 잘 부탁드립니다. 🙇‍♂️

이번 미션에서는 다음과 같이 설계한 후 진행했습니다.

DB 테이블 설계

erDiagram
  PRODUCT_LIST {
    BIGINT id PK
    VARCHAR name
    VARCHAR image
    INT price
  }

Loading

상품 관리 CRUD API

상품 Create

Request

POST /products HTTP/1.1
Host: localhost:8080
...

{
    "name": "망고",
    "image": "http://mango.png",
    "price": 1000
}

Response

HTTP/1.1 201 Created

상품 Retrieve

Request

GET /products HTTP/1.1
Host: localhost:8080
...

Response

HTTP/1.1 200 OK
...

[
    {
        "name": "망고",
        "image": "http://mango.png",
        "price": 1000,
        "id": 1
    },
    {
        "name": "디디",
        "image": "http://dd.png",
        "price": 2000,
        "id": 2
    }
]

상품 Update

Request

PUT /products/{id} HTTP/1.1
Host: localhost:8080
...

Response

HTTP/1.1 200 OK
...

{
    "name": "네오",
    "image": "http://neo.png",
    "price": 1000,
    "id": 1
}

상품 Delete

Request

DELETE /products/{id} HTTP/1.1
Host: localhost:8080
...

Response

HTTP/1.1 204 No Content

스프링에 대해 아직 익숙하지 않아서 여러모로 부족한 코드지만 잘 부탁드립니다 😁
추가로 궁금한 점은 코멘트로 남겨둘게요!

echo and others added 25 commits April 25, 2023 14:43
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
아래 메서드들 구현
- findByName
- deleteByID
- update

Co-authored-by: go-jaecheol <gojaech@naver.com>
아래 메서드들 테스트
- findByName
- deleteByID
- update

Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
Co-authored-by: go-jaecheol <gojaech@naver.com>
# Conflicts:
#	README.md
#	src/main/java/cart/product/domain/Product.java
#	src/main/java/cart/product/service/ProductListService.java
@Go-Jaecheol
Copy link
Author

Q1. URI에 ID를 노출시켜도 될까요??

Update나 Delete 요청을 할 때, PUT /admin/product/update/:id와 같은 형식으로 id를 통해 접근할 수 있도록 했습니다.
이렇게 id가 노출되도 되는지, 아니면 /admin/product/update/:name처럼 name을 노출시키고 내부에서 findIdByName()과 같은 메서드를 통해 id를 얻어서 값을 수정하도록 하는 것이 좋은지 궁금합니다!


Q2. REST API에서 URI 스타일

RESTful한 설계를 위해 URI를

  • /admin/product/update/{id}
  • /admin/product/{id}/update
  • /admin/product/{id}(PUT, DELETE 등 http method만 다르게)
    어떤 방식을 선택하는 게 좋은지 궁금합니다.

Copy link

@fucct fucct left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 망고.

전체적으로 테스트가 미흡한 부분이 있는것 같아요. 관련된 피드백과 함께 질문주신 부분은 코멘트에 남겨두었습니다.
궁금하신 부분 있으시면 코멘트 부탁드립니다!

@@ -1 +1 @@
rootProject.name = 'jwp-cart'
rootProject.name = 'jwp-shopping-cart'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

모듈명이 어쩌다 수정된걸까요? ㅋㅋㅋ..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intellij에서 프로젝트를 로드하는데 오류가 생겨서, settings.gradlerootProject.name을 프로젝트명과 동일하게 변경해 오류를 해결했습니다.

그런데 다른 크루들은 해당 오류가 발생하지 않았고, 페어의 노트북에서만 오류가 발생해서 IDE의 설정이나 버전 문제인지 정확하게 오류의 이유는 찾지 못했습니다..

settings.gradle이 하는 역할은 무엇인지, 그리고 저렇게 모듈명을 수정하면 안되는건지 궁금합니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

settings.gradle 은 다음 링크를 읽어보시면 좋을것 같아요!
https://galid1.tistory.com/645

왜 그런 오류가 있는지 저도 모르겠네요. 모듈명이 바뀐 케이스를 처음봐서 여쭤봤습니다 ㅎㅎ

import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ProductListController {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller 네이밍이 ProductList인데, 프로덕트리스트 페이지랑 어드민 페이지를 렌더하는 기능을 담고있네요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 컨트롤러는 페이지를 렌더링 해주는 기능을 가지고 있어서, PageController로 네이밍 변경했습니다.


크게 REST API 기능을 하는 컨트롤러페이지를 렌더링 하는 컨트롤러를 나눠서, ProductRestControllerPageController로 나눴는데
여기서 더 나아가서 PageController를 역할에 따라 HomeControllerAdminController로 나누는 게 좋을까요..?
당장은 큰 의미가 없을 것 같아서 하나의 컨트롤러에 두었는데, 확장성을 고려한다면 나누는 것도 좋아보여서 질문 드립니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

당장은 안바꿔도괜찮을것같아요.
다만 렌더해야하는 지면이 다양해진다면, 지면 특성별로 분류하는것도 관리측면에서 도움을 줄것 같네요.

return this.productListService.display();
}

@PostMapping("/product/create")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpMethod POST/PUT/DELETE 자체가 행위를 의미하기 때문에 path에 행위에 대한 키워드를 쓰시는것은 Restful 하지 않은것 같아요 :)

https://prohannah.tistory.com/156 요걸 읽어보시면 도움이 될것 같네요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

참고 문서 감사합니다 :)

다음과 같이 수정했습니다!

Method Path
GET /products
POST /products
PUT /products/{id}
DELETE /products/{id}

}

@PutMapping("/product/update/{id}")
@ResponseStatus(HttpStatus.CREATED)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update가 CREATED 응답을 받는게 맞을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음에는 새로운 값을 넣어준다라고 생각해서 CREATED가 맞을 것 같다고 생각했는데
보통 값이 없을 때 값이 생성되면 CREATED를, 값이 있을 때 값을 수정하면 OK를 반환하는 것 같군요.

OK 상태 코드를 반환하도록 수정했습니다!


@PostMapping("/product/create")
@ResponseStatus(HttpStatus.CREATED)
public void create(@RequestBody final RequestProductDto requestProductDto) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spring validation 라이브러리를 이용하여 @Valid 어노테이션 사용해보시면 좋을것 같습니다 :)


//then
final String productLiteral = result.body().asString();
System.out.println("productLiteral = " + productLiteral);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트에 출력이 있는 이유가 어떤걸까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분도 제대로 확인을 못했습니다..
RestAssured와 JsonPath에 익숙하지 않아서 값을 확인해본다는 걸 그대로 둔 것 같습니다 😥😥
수정하겠습니다!

.then()
.extract();

assertThat(result.statusCode()).isEqualTo(HttpStatus.CREATED.value());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integration test라면, dao를 주입받아 진짜로 저장이 되었는지도 확인해주셔야합니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProductDao를 주입받아 각 테스트 별로 값이 잘 저장되거나 수정, 삭제되었는지 확인하는 과정을 추가했습니다.

.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(requestProductDto)
.when()
.put("/admin/product/update/1")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실제로 id = 1 에 해당하는 product가 없을텐데, update가 되었다는걸 어떻게 검증할 수 있을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선 update 전에 해당 id가 값이 있는지 확인하고, 없으면 임의의 값을 넣어주는 과정을 추가했습니다..!

final var deleteResult = given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.when()
.delete("/admin/product/delete/2")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마찬가지로 id=2에 해당하는 product가 없을텐데 이거로 삭제검증이 가능할까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete의 경우에도 우선 해당 id가 값이 있는지 확인하고, 없으면 임의의 값을 넣어주는 과정을 추가했습니다.


import cart.product.dto.RequestProductDto;

public class Product {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

product의 테스트도 필요해보입니다.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Product 생성 테스트 추가했습니다..!

Copy link

@fucct fucct left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 망고!

피드백 사항이 많았는데 꼼꼼하게 반영해주셨네요!
크게 피드백 드릴 내용은 없는것 같아서 머지하겠습니다 :)
수고많으셨고 다음 미션 진행해주세요!

@fucct fucct merged commit 56d2887 into woowacourse:go-jaecheol May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants