ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링 인 액션] Chapter 2 - 웹 애플리케이션 개발하기 :: 폼 입력 유효성 검사하기
    개발서적읽기/Spring in Action 제 5판 2020. 7. 28. 13:42



    폼의 유효성 검사를 하는 방법으로 processDesign과 processOrder 메서드에 


    수많은 if/then블록을 너저분하게 하는 것이 있다.


    이 경우 데이터가 적합한지 각 필드에서 일일이 확인해야 한다.


    그러나 이것은 무척 번거롭고 코드 파악과 디버깅이 어렵다.


    다행히 스프링은 자바의 빈 유효성 검사(Bean Validation)를 지원한다.


    이것을 사용하면 애플리케이션에 추가 코드를 작성하지 않고 


    유효성 검사 규칙을 쉽게 선언할 수 있다.


    또한 스프링 부트를 사용하면 유혀성 검사 라이브러리를 프로젝트에 쉽게 추가할 수 있다.


    유효성 검사 API와 이 API를 구현한 Hibernate 컴포넌트는 


    스프링 부트의 웹 스타터 의존성으로 자동 추가되기 때문이다.


    스프링 MVC에 유효성 검사를 적용하려면 다음과 같이 해야 한다.


    - 유효성을 검사할 클래스(Taco, Order)에 검사 규칙을 선언한다.


    - 유효성 검사를 해야 하는 컨트롤러 메서드에 검사를 수행한다는 것을 지정한다.


    여기서는 DesignTacoController의 processDesign 메서드와


    OrderController의 processOrder 메서드가 해당된다.


    - 검사 에러를 보여주도록 폼 뷰를 수정한다.




    유효성 검사 API는 몇 가지 애노테이션을 제공한다.


    이 애노테이션들은 검사 규칙을 선언하기 위해 도메인 객체의 속성에 지정된다.


    유효성 검사 API를 구현한 Hibernate 컴포넌트에는 


    더 많은 유효성 검사 애노테이션이 추가되었다.


    지금부터는 Taco나 Order의 유효성 검사를 하는 애노테이션들의 적용 방법을 알아보자.




    ■유효성 검사 규칙 선언하기


    Taco 클래스의 경우는 name 속성의 값이 없거나 null인지 확인하고


    최소한 하나 이상의 식자재 항목을 선택했는지 확인할 필요가 있다.

    package tacos;
    /*
    * @USER JungHyun
    * @DATE 2020-07-04
    * @DESCRIPTION
    */

    import lombok.Data;

    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    import java.util.List;

    @Data
    public class Taco {
    @NotNull
    @Size(min = 5, message = "Name must be at least 5 characters long")
    private String name;

    @Size(min = 1, message = "You must choose at least 1 ingredient")
    private List<String> ingredients;
    }

    제출된 타코 주문의 유효성 검사를 하기 위해서는 Order 클래스에도


    유효성 검사 애노테이션을 적용해야 한다.


    배달 주소에 관한 속성들(street, city, state, zip)의 경우에는 


    사용자가 입력을 하지 않은 필드가 있는지 확인만 하면 되므로


    이때는 자바 빈 유효성 검사 API의 @NotBlank 애노테이션을 사용할 것이다.


    그러나 대금 지불에 관한 필드의 경우에는 다르다. ccNumber 속성의 경우는 


    값이 있는지는 물론이고, 입력 값이 유효한 신용 카드 번호인지도 확인해야 한다.


    ccExpiration 속성의 경우는 MM/YY(두 자리수의 월과 연도) 형식의 값이어야 한다.


    그리고 ccCVV 속성의 값은 세자리 수가 되어야 한다.


    이런 종류의 유효성 검사를 하려면 다른 자바 빈 유효성 검사 API 애노테이션과


    Hibernate Validator의 또 다른 애노테이션을 사용해야 한다.

    package tacos;
    /*
    * @USER JungHyun
    * @DATE 2020-07-04
    * @DESCRIPTION
    */

    import lombok.Data;
    import org.hibernate.validator.constraints.CreditCardNumber;

    import javax.validation.constraints.Digits;
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.Pattern;


    @Data
    public class Order {
    @NotBlank(message = "Name is required")
    private String deliveryName;
    @NotBlank(message = "Street is required")
    private String deliveryStreet;
    @NotBlank(message = "City is required")
    private String deliveryCity;
    @NotBlank(message = "State is required")
    private String deliveryState;
    @NotBlank(message = "Zip code is required")
    private String deliveryZip;
    @CreditCardNumber(message = "Not a valid credit card number")
    private String ccNumber;
    @Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$", message = "Must be formatted MM/YY")
    private String ccExpiration;
    @Digits(integer = 3, fraction = 0, message = "Invalid CVV")
    private String ccCVV;
    }




    ■폼과 바인딩될 때 유효성 검사 수행하기


    Taco와 Order의 유효성 검사 규칙 선언이 끝났다.


    다음으로 각 폼의 POST 요청이 관련 메서드에서 처리될 때


    유효성 검사가 수행되도록 컨트롤러를 수정하자.


    제출된 Taco의 유효성 검사를 하려면 DesignTacoController의 processDesign 메서드의


    인자로 전달되는 Taco에 자바 빈 유효성 검사 API의 @Valid 애노테이션을 추가해야 한다.

    @PostMapping
    public String processDesign(@Valid Taco design, Errors errors) {
    if (errors.hasErrors()) {
    return "design";
    }
    log.info("Processing design: " + design);
    return "redirect:/orders/current";
    }

    @Valid 애노테이션은 제출된 Taco 객체의 유효성 검사를 수행하라고 


    스프링 MVC에 알려준다.


    제출된 Order의 유효성 검사를 하려면 Taco와 마찬가지로


    OrderController의 processOrder 메서드를 변경하면 된다.

    @PostMapping
    public String processOrder(@Valid Order order, Errors errors) {
    if (errors.hasErrors()) {
    return "orderForm";
    }
    log.info("Order submitted: " + order);
    return "redirect:/";
    }

    이렇게 요청에 에러가 있으면 사용자가 입력 오류를 수정할 수 있도록


    해당 요청이 폼 뷰에 다시 보내진다.


    그러나 무엇을 수정해야 할지 사용자가 어떻게 알까?




    ■유효성 검사 에러 보여주기


    Thymeleaf는 fields와 th:errors 속성을 통해 


    Errors 객체의 편리한 사용 방법을 제공한다.

    <h3>Here's how I'll pay...</h3>
    <label for="ccNumber">Credit Card #: </label>
    <input type="text" th:field="*{ccNumber}"/>
    <span class="validationError"
    th:if="${#fields.hasErrors('ccNumber')}"
    th:errors="*{ccNumber}">CC Num Error</span>
    <br/>

    th:error 속성은 ccNumber 필드를 참조한다.


    그리고 이 필드에 에러가 있다고 가정하고 


    <span>에 사전 지정된 메시지(CC Num Error)를 검사 에러 메세지로 교체한다.

    댓글

Designed by Tistory.