ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 상품 등록 범위 검증 - V1
    스프링/스프링 MVC 패턴 2023. 2. 22. 19:23

    상품 등록 페이지를 만들었는데, 상품명을 입력하지 않아도 상품으로 등록되고, 가격과 수량을 아무렇게나 입력해도 등록이 된다. 실제로는 이렇게 사용하면 안되니까 몇 가지의 제한을 걸 것이다.

     

    상품명 : 빈칸이면 안됨

    수량 : 최대 9999개까지 허용

    가격 : 1000원~100만원까지 허용

    수량 * 가격이 10000원 이상이어야지만 등록 가능

     

    @PostMapping("/add")
    public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes, Model model) {
        // 검증 오류 결과를 보관
        Map<String, String> errors = new HashMap<>();
    
        // 검증 로직
        if (!StringUtils.hasText(item.getItemName())) {
            errors.put("itemName", "상품 이름은 필수입니다.");
        }
        if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
            errors.put("price", "가격은 1,000 ~ 1,000,000 까지 허용합니다.");
        }
        if (item.getQuantity() == null || item.getQuantity() >= 9999) {
            errors.put("quantity", "수량은 최대 9,999까지 허용합니다.");
        }
    
        // 특정 필드가 아닌 복합 룰 검증
        if (item.getPrice() != null && item.getQuantity() != null ) {
            int resultPrice = item.getPrice() * item.getQuantity();
            if (resultPrice < 10000) {
                errors.put("globalError", "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice);
            }
        }
    
        // 검증에 실패하면 다시 입력 폼으로 이동하는 로직
        if (!errors.isEmpty()) {
            log.info("errors = {}", errors);
            model.addAttribute("errors", errors);
            return "validation/v1/addForm";
        }
    
        // 아래는 에러가 없을 때의 성공 로직
    
    
        Item savedItem = itemRepository.save(item);
        redirectAttributes.addAttribute("itemId", savedItem.getId());
        redirectAttributes.addAttribute("status", true);
        return "redirect:/validation/v1/items/{itemId}";
    }

    우리가 예전에 짰던 코드중에 /add 페이지로의 PostMapping이 있었다. 상품 등록을 하면 등록이 되면서 상세 페이지로 넘어가는 코드였다. 여기서 수정을 통해 위의 조건을 충족하지 않으면 상품 등록도 되지않고, 상품 등록 페이지를 다시 보여주는 그런 코드로 수정을 했다.

     

    상품 등록을 하지 않았을 경우 (저장을 눌러도 다시 이 페이지로 돌아오게 된다.)

     

    로그로 찍어보면 에러 메시지가 로그에 출력된다.

     

     

     

     

    아직까지는 url 처리만 진행해서 조건에 충족하지 않아서 상품 등록이 안되어도 왜 등록이 안되고 넘어가지 않는지 확인할 수 없다. 따라서 해당 에러를 사용자에게 보여주는 기능도 만들어야 한다.

     

     

    addForm에서 코드를 추가할 것이다.

     

    추가할 코드는 크게 2가지이다.

    <div class="field-error" th:if="${errors?.containsKey('itemName')}"th:text="${errors['itemName']}">
        상품명 오류
    </div>

    첫 번째로 어떠한 오류인지 출력해주는 코드이다.

     

    <input type="text" id="itemName" th:field="*{itemName}"
           th:class="${errors?.containsKey('itemName')} ? 'form-control field-error' : 'form-control'"
           class="form-control" placeholder="이름을 입력하세요">

    두 번째로 코드가 사용자에게 잘 보이게 빨간색으로 보여주는 코드이다.

     

     

    상품명 오류, 가격 오류, 수량 오류를 전부 이와 같이 넣어주면 된다.

     

     

    <div th:if="${errors?.containsKey('globalError')}">
        <p class="field-error" th:text="${errors['globalError']}">전체 오류 메시지</p>
    </div>
    
    <div>
        <label for="itemName" th:text="#{label.item.itemName}">상품명</label>
        <input type="text" id="itemName" th:field="*{itemName}"
               th:class="${errors?.containsKey('itemName')} ? 'form-control field-error' : 'form-control'"
               class="form-control" placeholder="이름을 입력하세요">
        <div class="field-error" th:if="${errors?.containsKey('itemName')}"th:text="${errors['itemName']}">
            상품명 오류
        </div>
    </div>
    <div>
        <label for="price" th:text="#{label.item.price}">가격</label>
        <input type="text" id="price" th:field="*{price}"
               th:class="${errors?.containsKey('price')} ? 'form-control field-error' : 'form-control'"
               class="form-control" placeholder="가격을 입력하세요">
        <div class="field-error" th:if="${errors?.containsKey('price')}"
             th:text="${errors['price']}">
            가격 오류
        </div>
    </div>
    <div>
        <label for="quantity" th:text="#{label.item.quantity}">수량</label>
        <input type="text" id="quantity" th:field="*{quantity}"
               th:class="${errors?.containsKey('quantity')} ? 'form-control field-error' : 'form-control'"
               class="form-control" placeholder="수량을 입력하세요">
        <div class="field-error" th:if="${errors?.containsKey('quantity')}"
             th:text="${errors['quantity']}">
            수량 오류
        </div>
    </div>

    만들어진 최종 코드이다. (위 아래 생략)

     

    조건에 충족하지 않으면 해당 부분의 내용을 사용자에게 출력해준다.

Designed by Tistory.