[Toy Project] 제품 등록 API 생성

최지나·2023년 10월 14일
5
post-thumbnail

드디어 API 생성을 시작하였다,,!
제품 재고 관리 시스템에서 메인이라고 할 수 있는 👜제품👜에 대한 등록 API를 생성해보았다


API 정의

  • method: POST
  • endpoint: /api/v1/product
  • Request Body Example
{
    "name": "귀여운한라봉",
    "categoryName": "과일",
    "price": 10000,
    "stock": 20
}
  • 제품을 등록하려면 이미 category가 등록되어 있어야 하지만, 제품 등록을 목표로 삼았기에, category 테이블에 하나의 sample 카테고리를 등록해 놓은 뒤 개발을 진행하였다.

CODE

1. controller

    @PostMapping
    public ResponseEntity<Object> create(
            @RequestBody @Valid ProductInput productInput,
            Errors errors) {

        if (errors.hasErrors()) {
            return new ResponseEntity<>(errorUtil.getErrorMessages(errors), HttpStatus.BAD_REQUEST);
        }

        productService.createProduct(productInput);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

2. Service

   public void createProduct(ProductInput productInput) {

        Product existProduct = productRepository.findByName(productInput.getName());
        if (existProduct != null) {
            throw new ResponseStatusException(HttpStatus.CONFLICT, "409: PRODUCT ALREADY EXIST");
        }

        String lastProductCode = productRepository.findLastProductCode();
        if (lastProductCode == null) {
            lastProductCode = "product_0";
        }

        int sequence = Integer.parseInt(lastProductCode.split("_")[1]);
        String newProductCode = "product_" + (sequence + 1);
        
        Category existCategory = categoryRepository.findByName(productInput.getCategoryName());
        if (existCategory == null) {
            throw new ResponseStatusException(HttpStatus.CONFLICT, "404: CATEGORY NOT FOUND");
        }

        Product product = Product.builder().productCode(newProductCode).category(existCategory)
                .name(productInput.getName()).price(productInput.getPrice()).stock(productInput.getStock())
                .img(productInput.getImg()).barcode(productInput.getBarcode())
                .description(productInput.getDescription()).build();

        productRepository.save(product);
    }

3. input

public class ProductInput {

    @NotBlank(message = "제품 명은 반드시 있어야 합니다")
    @Pattern(regexp = "^.{4,29}$", message = "사용자 명은 5자 이상 30자 미만이어야 합니다.")
    private String name;

    @NotNull(message = "카테고리는 반드시 하나 선택해야 합니다")
    private String categoryName;

    @NotNull(message = "가격은 반드시 있어야 합니다")
    private BigDecimal price;

    @NotNull(message = "재고 수량은 반드시 있어야 합니다")
    private int stock;

    private String img;

    private String barcode;

    private String description;

}

4. Repository

@Repository
public interface CategoryRepository extends CrudRepository<Category, String> {

    Category findByName(String name);
}
@Repository
public interface ProductRepository extends CrudRepository<Product, String> {

    Product findByName(String name);

    @Query("SELECT MAX(p.productCode) FROM Product p")
    String findLastProductCode();
}

API 실행 결과

  • Postman Result

  • Database(PostgreSQL Result)

개선이 필요한 사항

기본적인 API 하나를 구현하고 나니 필요한 👑개선이 필요한 사항👑들이 눈에 더 보이기 시작했다.

  • table에 등록일자, 업데이트 일자를 추가
    • 언제 제품 | 매장 | (카테고리) 이 등록|수정 되었는지를 기록하면 관리자 입장에서 확인할 수 있는 유용한 정보가 더 많아질 것 같다. ex) 특정 제품의 가격 수정 일자 확인
  • custom sequece generator를 사용하여 pk 자동 증가하게 처리
    • 서비스에서 seq를 늘려서 저장하게 되면, 제품이 삭제되었을 때나, 여러 등록 요청을 동시에 받았을 때 문제가 생길 수 있기에, product 등록 시 product_code가 자동 생성되게 수정해야 한다
  • 성공 시 성공 메시지를 return하도록 추가하자
  • 에러 발생 시 에러 메시지가 지나치게 길게 찍히는데, 이를 UI에서 뿌려주기 쉽도록 필요한 에러 메시지를 필터링하여 제공하자
  • 위의 내용들 개선 뒤에, 추후 다른 API 개발에서는 TDD를 사용해보자

,,,많다


혼자 API 개발의 전체 flow를 돌려 보니 놓쳤던 부분들이 많이 발견되는 것 같다
차근차근 진행해나가면서 성장했으면 좋겠다
화이팅이다 😊😊

profile
의견 나누는 것을 좋아합니다 ლ(・ヮ・ლ)

0개의 댓글