본 프로젝트 자료는 김영한님의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고 제작됐음을 알립니다.
지금까지 만든 웹 애플리케이션은 폼 입력시 숫자를 문자로 작성하거나해서 검증 오류가 발생하면 오류 화면으로 바로 이동했다.
이 부분이 발생하지 않게 직접적으로 화면에 오류를 띄울 수 있게 만들어 볼려고 한다.
예시 화면
컨트롤러의 중요한 역할중 하나는 HTTP 요청이 정상인지 검증하는 것이다.
그리고 정상 로직보다 이런 검증 로직을 잘 개발하는 것이 어쩌면 더 어려울 수 있다.
자 그럼, 지금부터 이 화면을 만들 수 있게 목표로 하고 작업 해볼까 한다.
위 사진과 같이 고객이 상품 등록 폼에서 상품명을 입력하지 않거나, 가격, 수량 등이 너무 작거나 커서 검증 범위를 넘어서면, 404 화면이나 500 화면 보다는 서버 검증 로직이 실패해야 한다. 이렇게 검증에 실패한 경우 고객에게 다시 상품 등록 폼을 보여주고, 어떤 값을 잘못 입력했는지 친절하게 알려주어야 한다.
현재 요구사항에 맞게 검증 로직을 작성해보고 이해해보고자 한다.
예제 코드
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes, Model model) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v1/items/{itemId}";
}
성공 했을 때의 로직 안에 실패 했을 경우의 수를 만들어줘야 위에 요구사항에 맞게 수정할 수 있다. 우선,
검증했을 때 실패 시 어떠한 오류가 생겼는지 정보를 저장해주는 보관소를 만들어야 한다.
추가 로직
특정 필드를 넘어서는 오류를 처리해야할 때 필드명을 Key 를 사용할 수 없어 global 을 이용해 대체 Key 로 입력한다.
만약 검증에서 오류 메시지가 하나라도 있으면 오류 메시지를 출력하기 위해 model 에 errors 를 담고, 입력 폼이 있는 뷰 템플릿으로 보낸다.
이제 오류 출력할 로직이 준비 끝났으면 HTML로 넘어가 마무리를 해보자.
HTML
상품 등록 form 안에 div(전체 오류 메시지) 를 집어넣어 복합 오류가 발생했을 때 감지 및 오류 처리를 하게 해준다.
그 이후 단일 로직들은 각 input 에 검증 로직을 넣어 입력 오류가 발생 시 오류 처리해줄 수 있게 처리해준다.
입력했을 경우 오류 발생 시 아래와 같이 화면에 출력된다.
복합오류 같은 경우 타임리프의 th:if 를 사용해 조건을 만족했을 경우 해당 오류 메시지를 출력해준다.
나머지들도 똑같이 적용해주면 끝난다.
가격 입력 창
입력했을 경우 오류 발생 시 아래와 같이 화면에 출력된다.
수량 입력 창
입력했을 경우 오류 발생 시 아래와 같이 화면에 출력된다.
출력 결과
하지만 경고로 보기엔 글씨가 검정색이라 검정으로 보이지 않고 경고라고 인식하기엔 색상이 경각심을 심어주지 않는다.
빨간색으로 변환시켜보자.
HTML Style
넣어주면 빨간색으로 출력할 수 있다.
ㅁ 경고 메시지 색상 변경
ㅁ 테두리도 같이 색상 변경 시켜줬다.
결과 화면
바인딩리절트 는 위에 배운 방식을 좀 더 효율적으로 코드를 고치기 위해 사용해볼려고 한다.
검증 로직
글로벌 오류 메시지
검증에 실패하면 다시 입력 폼으로
특정 필드의 범위를 넘어서는 검증 로직
필드 오류 - FieldError
뒤로 HTMl 도 수정해줘야 작동하는지 확인할 수 있다.
HTML
코드가 간결해진걸 확인할 수 있다.
위 코드 작동 방식
이렇게 코드를 변경하면 잘못된 값을 입력하더라도 코드가 유지하는 모습을 확인할 수 있다.
위 사진과 같이 가격은 Integer 로 설정되어 있어 문자를 입력 할 경우 보관할 방법이 없어 저장되지 않는다. 하지만 FieldError 는 오류 발생시 사용자 입력 값을 저장하는 기능을 제공해 유지하는 모습을 보여준다.
여기서 rejectedValue 가 바로 오류 발생시 사용자 입력 값을 저장하는 필드다.
bindingFailure 는 타입 오류 같은 바인딩이 실패했는지 여부를 적어주면 된다. 여기서는 바인딩이 실패한 것은 아니기 때문에 false 를 사용한다.