Validation/errorMessage

Shaun·2022년 10월 3일
1

ThymeLeaf

목록 보기
4/4
post-thumbnail

검증

  • 간단히 말해 클라이언트가 서버에서 받을 데이터타입에 맞게 보내는지 확인하는 절차

  • ex : 몸무게 입력칸에 한글 입력...etc

직접검증

  • 순수 검증 코드를 만들어보자

  • 검증시 오류가 발생하면 errors 에 담아둔다. 이때 어떤 필드에서 오류가 발생했는지 구분하기 위해 오류가 발생한 필드명을 key 로 사용한다.

  • 검증오류가 나면 Model에 담아서 뷰단으로 던진다.

  • 던진 에러에 th:if = "#{errors?.contains('key')}" 키값이 있으면 키값에 해당하는 value 반환

중요

  • 해당 페이지 처음 들어갈떄 errors 에 null이 들어있을텐데 왜 익셉션이 안터졌을까???
  • 바로 erros.? 문법때문. 익셉션 대신에 null반환
  • 타임리프에서 null이면 해당 코드는 무시됌(아무일도f 안일어남)

스프링 검증

  • 직접 검증 코드를 작성 하는 방법도 있지만 뷰단 코드를 작성할때나 중복되는 코드도 많기에 좋지 않은 방법이다. 스프링은 어떻게 검증을 처리하는지 살펴보자

BindingResult

  • 스프링에서는 BindingResult 라는 것을 사용한다. 사용할때 주의해야 할점은 검증을 할 객체가 앞에 와야한다는점

  • 해당 객체 필드에 에러가 나면 FieldError 객체를 생성해 BindingResult 에 넣어준다.

  • 객체 에러시 ObjectError 에 담아 BindingReuslt에 넣어준다

  • filedError("객체이름","필드이름","디폴트 메시지")

  • ObjectError("객체이름","디폴트 메세지")

  • model에 안담아줘도 bindingResult는 알아서 뷰단에 넘어감

  • 해당 필드에 오류가 있으면 출력 없으면 무시

  • 컨트룰러 필드에러 객체에 price라는 필드이름으로 담아와서 저렇게만 사용해도 가능

  • 글로벌 오류는 하나가 이상일수 있다.

  • 첫번째의 복잡했던 코드를 th:errorclass로 바꿀수 있다.
  • #field , #fields 로 bindingResult에 제공하는 오류에 접근 가능

  • th:errors 는 해당 필드에 오류가 있으면 출력 아니면 x

  • th:errorclass 는 th:field 에서 지정한 오류가 있으면 class 정보 추가(여기서는 CSS)

BindingResult 2

  • BindgResult 는 Error인터페이스를 상속한 인터페이스이므로 Errors 를 사용해도 됀다.

  • 하지만 BindingResult가 제공하는 기능이 더 많으며 관례상 BindingResult를 많이 사용함

FieldError / ObjectError

  • 클라이언트가 검증실패를 유도하는 값을 넣었을떄 칸에 남아있게 하는 방법(타입오류)
  • 세번째 메서드는 클라이언트가 검증실패를 유도하는 값, 네번째는 binding이 잘됐는지 안됐는지

  • th:field 에서 이 세번째값을 꺼내서 사용하는것. 즉 사용자가 잘못입력한 값

  • th:field를 사용하면 정상적인 값이 올때는 객체에서 필드값을 꺼내 사용하고 타입이 잘못됐으면 스프링이 알아서 fieldError에 잘못 입력한 값을 넣어 bindingResult에 넣어서 보낸 값을 꺼내서 반환함.

오류메시지 처리

  • 그냥 FieldError로 나오는 오류메시지는 알아보기가 힘들다. 우리가 커스터 마이징해보자

  • fieldError 에 Codes, arguments 는 오류 발생시 오류 코드로 메시지를 찾기 위해 사용된다.

  • codes: 배열 형태로 여러값을 넣을수 있으며 처음 매칭되는 메시지 사용

  • arguments: 치환할 값 전달

  • 저번에 배웠던 메세지 기능을 사용하면 됀다. 당연히 이것도 국제화 적용 가능

MessageCodesResolver

ObjectError

bindingResult -reject()

  • 위에 쓰던 예전 방법은 에러 메세지도 일일이 넣어주고 그러면 그럴수록 파라미터도 많아지며 복잡해진다. 이럴땐 간단하게 bindingResult에서 제공하는 reject() 메서드를 사용 하면 됀다.

  • bindingResult는 이미 target이 누군지 안다는 점을 이용한다. 그러므로 field값을 적고, errorcode만 입력해주면 됀다. fieldError 처럼 aaa.bbb.ccc 로 작성할 필요가 없이 aaa만 입력하면 됀다. 그럼 알아서 properties 메세지에서 알아서 찾아옴

  • reject()rejectValue()는 기본적으로 좀더 디테일한 경로의 오류메세지가 있으면 그걸 우선적으로 반환한다.

  • 그런데 어떻게 errorCode하나만 보냈는데 알아서 디테일한 경로 오류메세지가 있으면 그걸 우선해서 가져오는 것일까??

FieldError

bindingResult - rejectValue()

  • 필드에러도 마찬가지이다. 이 에러 내용을 출력하는 방식보다 간단한 방법은 rejectValue()를 사용하는것


  • 여기서 주목해야할점은 필드에러 또한 required 만 보냈을뿐인데 어떻게 더 디테일한 경로 오류메세지가 있으면 그것먼저 우선해서 가져오는 것일까??

  • bindingResult의 reject() , rejectValue() 는 내부적으로 messagesCodesResolver 를 사용한다.

  • messageCodesResolver는 특정 규칙이 있다. 그 규칙대로 가져오는것

  • messageCodesResolver은 저렇게 메세지를 만들고저 값들을 각각
    new ObjectError(new Stirng[])/ new FieldError(new String[])
    에 나온 값들을 순서대로 넣어주고 순서대로 찾는것.

=> 즉 변경 요청이와도 개발코드는 변경할 필요없고 error.properties만 수정하면 됌

스프링이 직접만든 오류메세지

  • 주로 타입정보가 맞지 않을때 발생 , 스프링이 자동 생성

  • codes[typeMismatch.item.price,typeMismatch.price,typeMismatch.java.lang.Integer,typeMismatch

  • 위에 예제처럼 4가지로 messageCodesResolver가 만들어서 보내준다. 만약 errors.properties 에 저 4가지 내용들이 없으면 스프링이만든 디폴트 메세지 출력

  • 임시로 두가지를 만들어봤다. 우선순위(디테일 경로)에 따라 출력해준다.

Validator ( 검증로직 분리)

  • 컨트룰러의 검증로직이 너무크고 복잡하다. 코드 독립성을위해 따로 분리해주자.

  • support() = 해당 검증기를 지원하는지 여부 확인용

  • 이렇게 validate 인터페이스를 사용하면 한가지 기능을 더 사용 할수있다. 바로 WebDataBinder
  • 해당 컨트룰러에 검증기 자동적용

  • @Validated 애노테이션을 사용하면 WebDataBinder에 등록된 검증기를 사용한다

  • 이때 검증기가 여러개일수 있다. 이럴때는 만들어 놓았던 supports()가 사용됀다.

profile
호주쉐프에서 개발자까지..

0개의 댓글