🔷 Spring in Action - 2.웹 애플리케이션 개발하기 _ 2.3 폼 입력 유효성 검사하기, 2.4 뷰 컨트롤러로 작업하기
✔ 2.3 폼 입력 유효성 검사하기
- 스프링은 자바의 빈 유효성 검사(Bean Validation API)를 지원한다
=> 애플리케이션에 추가 코드를 작성하지 않고 유효성 검사 규칙을 쉽게 선언할 수 있다
- 스프링 부트를 사용하면 유효성 검사 라이브러리를 프로젝트에 수비게 추가할 수 있다
=> 유효성 검사 API와 이 API를 구현한 Hibernate 컴포넌트는 스프링 부트의 웹 스타터 의존성으로 자동 추가되기 때문
🎈 스프링 MVC에 유효성 검사 적용 방법
- 유효성 검사할 클래스에 검사 규칙 선언
- 유효성 검사를 해야하는 컨트롤러 메서드에 검사를 수행한 다는 것을 지정
- 검사 에러를 보여주도록 폼 뷰를 수정
✔ 2.3.1 유효성 검사 규칙 선언하기
-
Taco 도메인 클래스에 유효성 검사 규칙 추가 코드
package tacos; import lombok.Data; import java.util.Date; import java.util.List; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @Data public class Taco { private Long id; private Date createdAt; // @NotNull, @Size() : 유효성 검사 규칙 선언 // name 속성에는 값이 null 이면 X, 최소 5개문자여야 한다 @NotNull @Size(min=5, message="Name must be at lease 5 characters long") private String name; // jdbc연결 위해 변경 @Size(min=1, message="You must choose at lease 1 ingredient") private List<String> ingredients; }
-
주문 필드의 유효성 검사 규칙 추가 코드
package tacos; import lombok.Data; import javax.validation.constraints.Digits; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.CreditCardNumber; import java.util.ArrayList; import java.util.Date; import java.util.List; @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 is required") private String deliveryZip; // @CreditCardNumber : 속성의 값이 Luhn 알고리즘 검사에 합격한 유요한 신용 카드 번호이어야 한다는 것을 선언 @CreditCardNumber(message = "Not a valid credit card number") private String ccNumber; // Pattern 어노테이션에 정규 표현식을 지정하여 속성 값이 해당 형식을 따르는지 확인 @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; }
❓ @NotBlank 대신 @NotNull을 쓰면 안되는지? => @NotNull 은 빈공간(스페이스) 입력이 가능하지만 @NotBlank 은 빈공간(스페이스) 입력이 불가하다 -> 스페이스 입력을 방지하기 위해 @NotBlank 을 사용!
✔ 2.3.2 폼과 바인딩될 때 유효성 검사 수행하기
-
제출된 Taco의 유효성 검사 추가 코드
package tacos.web; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import lombok.extern.slf4j.Slf4j; import tacos.Taco; import tacos.Ingredient; import tacos.Ingredient.Type; import javax.validation.Valid; import org.springframework.validation.Errors; import tacos.data.IngredientRepository; import tacos.data.TacoRepository; @Slf4j // @Controller : 해당 클래스가 컨트롤러로 식별되게 하며 컴포넌트 검색을 해야한다는 것을 나타냄 // => 스프링이 해당클래스를 찾은후 스프링 APP컴텍스트의 빈(Bean)으로 해당 클래스의 인스턴스를 자동 생성한다 @Controller // @RequestMapping : 해당 클래스가 처리하는 요청의 종류 // 요청 경로가 disign 인 HTTP GET 요청 처리 @RequestMapping("/design") // Order의 다수의 HTTP 요청에 걸처 존재 해야한다 => 다수의 타코를 생성하고 하나의 주문으로 추가할 수 있게 하기 위해 // 클래스 수즌의 @SessionAttributes 을 주문과 같은 모델 객체에 지정 => 세션에서 계속 보존되면서 다수의 요청에 걸쳐 사용될 수 있다 @SessionAttributes("order") public class DesignTacoController { // /design 경로의 POST 요청을 처리 => taco 를 디자인 하는 사용자가 제출한 것을 여기에서 처리한다 @PostMapping // processDesign() 메서드에서는 taco 객체를 사용해서 어떤 것이든 원하는 처리를 할 수 있다 // @Valid : 제출된 taco 객체의 유효성 검사를 수행 하라고 스프링 MVC 에 알려준다 public String processDesign(@Valid Taco design, Errors errors){ // Errors 객체의 hsErrors() 메서드를 호출하여 검사 에러가 있는지 확인 // 에러가 있으면 taco 의 처리를 중지하고 "disign" 뷰 이름을 반환하여 폼이 다시 보이게 한다 if(errors.hasErrors()){ return "design"; } log.info("Processing design: " + design); // redirect : processDesign()의 실행이 끝난 후 사용자의 브라우저가 /orders/current 상대 경로로 재접속되어야 한다는 것을 나타낸다 return "redirect:/orders/current"; } }
❓ @Valid : 제출된 taco 객체의 유효성 검사를 수행 하라고 스프링 MVC 에 알려준다 는게 무슨뜻? => MVC 에 붙어있는 어노테이션 들에게 알려주는것 같다
-
제출된 Order의 유효성 검사 추가 코드
package tacos.web; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import tacos.Order; import javax.validation.Valid; @Slf4j @Controller // @RequestMapping : /orders 로 시작되는 경로의 요청을 이 컨트롤러의 요청 처리 메서드가 처리한다는 것을 알려주는 애노테이션 @RequestMapping("/orders") @SessionAttributes("order") public class OrderController { // Order 유효성 검사 @PostMapping public String processOrder(@Valid Order order, Errors errors) { if (errors.hasErrors()) { // orderForm 을 리턴한다 return "orderForm"; } log.info("Order submitted: " + order); return "redirect:/"; } }
✔ 2.3.3 유효성 검사 에러 보여주기
- 주문 폼의 모든 필드에 span 추가 코드
<span class="validationError" th:if="${#fields.hasErrors('ccCVV')}" th:errors="*{ccCVV}">CC Num Error</span>
▶ 유효성검사 출력
✔ 2.4 뷰 컨트롤러로 작업하기
- 뷰에 요청을 전달하는 일만 하는 컨트롤러(뷰 컨트롤러)를 선언하는 방법
-
뷰 컨트롤러 선언 코드
package tacos.web; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; // 뷰 컨트롤러의 역할을수행하는 구성 클래스 // WebMvcConfigurer : 스프링 MVC를 구성하는 메서드를 정의하는 인터페이스 @Configuration public class WebConfig implements WebMvcConfigurer { @Override // addViewControllers()는 하나 이상의 뷰 컨트롤러를 등록하기 위해 사용할 수 있는 // ViewControllerRegistry 를 인자로 받는다 public void addViewControllers(ViewControllerRegistry registry) { // 뷰 컨트롤러가 GET 요청을 처리하는 경로인 "/" 를 인자로 전달해 // addViewController()를 호출한다 => ViewControllerRegistry 객체를 반환한다 // setViewName("home") : "/" 경로의 요청이 전달되어야 하는 뷰로 home 을 지정 registry.addViewController("/").setViewName("home"); } }
❓ WebMvcConfigurer 인터페이스는 왜 메서드 하나만 선택해서 구현이 가능할까? => 인터페이스의 메서드 앞에 defualt 가 붙어있으면 선택적ㄴ 구현이 가능하다
✔ 2. 웹 애플리케이션 개발하기 요약
- 스프링은 스프링 MVC라는 웹 프레임워크를 제공 -> 스프링 애플리케이션의 웹 프론트엔드 개발에 사용
- 스프링 MVC는 애노테이션을 기반으로 하고 @RequestMapping, @GetMapping, @PostMapping 을 사용해 요청 처리 메서드를 선언할 수 있다.
- 대부분 요청 처리 메서드들은 마지막에 Thymeleaf 템플릿과 같은 논리 뷰 이름을 반환
=> 모델 데이터와 함께 해당 요청을 전달하기 위해
- 스프링 MVC는 자바 빈 유효성 검사 API 와 Hibernate Validator 등 유효성 검사 API 구현 컴포넌트를 통해 유효성 검사를 지원한다.
- 모델 데이터가 없거나 처리할 필요가 없는 HTTP GET 요청을 처리할 때는 뷰 컨트롤러를 사용할 수 있다
- Thymeleaf에 추가해 스프링은 다양한 뷰 템플릿을 지원한다