FireDrago

[Spring] 검증처리 본문

프로그래밍/Spring

[Spring] 검증처리

화이용 2024. 2. 9. 15:14

 

스프링은 클라이언트가 잘못된 입력값을 입력했을때 유효성을 검사하고, 발생한 에러를 처리하는 편리한 기능을 제공한다

이러한 검사는 클라이언트 단계에서 할 수도 있지만, 조작과 보안 위험이 있으므로 서버단에서도 반드시 검사해야한다

 

< BindingResult > 

스프링은 BindingResult 인터페이스를 통하여 여러 에러상황을 저장하고 오류메시지를 전달하는 기능을 한다.

반드시 @ModelAttribute 객체의 바로뒤에서 호출해야한다.

addError( ) 를 사용하면, 사용자의 잘못입력한 값을 그대로 전달 할 수 있다.

필드값의 에러인 경우 FieldError , 그외 에러인 경우 ObjectError 객체를 생성하여 파라미터로 전달한다.

코드를 살펴보자

FieldError 객체의 생성자는 사용자의 잘못된 입력값을 저장하고, 오류메시지를 만드는데 필요한 값을 받는다.

objectName : 오류가 발생한 객체 이름
field : 오류 필드
rejectedValue : 사용자가 입력한 값(거절된 값)
bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값
codes : 메시지 코드
arguments : 메시지에서 사용하는 인자
defaultMessage : 기본 오류 메시지

파라미터의 타입오류 등 바인딩에서 발생한 오류처리에 쓰이는

ObjectError 역시 오류필드 값을 받지않는다는 점 빼고 FieldError와 같다

 

<Thymeleaf>

여기서 스프링과 연계된 타임리프의 편리함을 알 수 있다. 코드로 살펴보자

BindingResult에 ObjectError 가 있으면 태그를 표시하기 위해 #fields.hasGlobalErrors()를 사용했다.

#fields.hasErrors('필드명') 을 사용하면 특정 필드의 에러도 확인 할 수 있다.

 

두번째 이미지에서 th:errorclass="field-error"  를 통해 에러가 있는경우 class 속성을 추가할수 있도록 했다.

th:errors="*{price}" 는 앞의 코드에서 th:object="객체" 로 정의된 객체의 price필드에 에러가 있을경우 태그를 표시한다

th:field는 엄청 똑똑하게 작동하는데, 오류가 있으면, 필드의 오류값을, 오류가 없으면 정상적인 값을 value로 출력한다

 

< rejectValue( ) , reject( ) >

addErrors(  ) 메서드는 여러기능을 지원하지만 파라미터가 많아, 코드가 복잡해진다. 

그래서 BindingResult 인터페이스는 reject (객체), rejectValue(필드) 메서드를 통해 편리한 오류처리를 지원한다.

어차피 BindingResult 는 @ModelAttribute 바로뒤에 호출되므로, 객체이름은 이미 알 수 있다.

파라미터로 전달 할 필요가 없는 것이다. 코드로 살펴보자

addError( ) 보다 훨씬 더 간결한 코드로 에러는 처리 할 수 있다. 

그런데 에러코드를 addError( ) 보다 훨씬 단순하게 처리한 것이 보인다.

MessageCodeResolver 가 내부에서 에러코드를 생성해주기 때문이다. 에러코드에 대하여 알아보자

 

< 에러코드 >

MessageCodeResolver는 객체오류, 필드오류에 따라 오류코드를 다른 순서로 생성한다.

객체 오류의 경우 다음 순서로 2가지 생성
1.: code + "." + object name
2.: code
예) 오류 코드: required, object name: item
1.: required.item
2.: required

 

필드 오류의 경우 다음 순서로 4가지 메시지 코드 생성
1.: code + "." + object name + "." + field
2.: code + "." + field
3.: code + "." + field type
4.: code
예) 오류 코드: typeMismatch, object name "user", field "age", field type: int
1. "typeMismatch.user.age"
2. "typeMismatch.age"
3. "typeMismatch.int"

 

순서대로 생성된 에러코드에 맞는 에러메시지를 properties 파일에서 찾고, 해당되는 에러메시지가 있는경우 출력한다.

#==ObjectError==
#Level1
totalPriceMin.item=상품의 가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}

#Level2 - 생략
totalPriceMin=전체 가격은 {0}원 이상이어야 합니다. 현재 값 = {1}


#==FieldError==
#Level1
required.item.itemName=상품 이름은 필수입니다.
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
max.item.quantity=수량은 최대 {0} 까지 허용합니다.

#Level2 - 생략

#Level3
required.java.lang.String = 필수 문자입니다.
required.java.lang.Integer = 필수 숫자입니다.
min.java.lang.String = {0} 이상의 문자를 입력해주세요.
min.java.lang.Integer = {0} 이상의 숫자를 입력해주세요.
range.java.lang.String = {0} ~ {1} 까지의 문자를 입력해주세요.
range.java.lang.Integer = {0} ~ {1} 까지의 숫자를 입력해주세요.
max.java.lang.String = {0} 까지의 문자를 허용합니다.max.java.lang.Integer = {0} 까지의 숫자를 허용합니다.

#Level4
required = 필수 값 입니다.
min= {0} 이상이어야 합니다.
range= {0} ~ {1} 범위를 허용합니다.
max= {0} 까지 허용합니다.

#추가
typeMismatch.java.lang.Integer=숫자를 입력해주세요.
typeMismatch=타입 오류입니다.

스프링은 타입 오류가 발생하면 typeMismatch 라는 오류 코드를 사용한다. 

생성된 오류 코드를 순서대로 조회한뒤, 해당 오류코드의 메시지를 출력하는 방식이다.

즉 개발자는 구체적인 오류메시지 부터, 범용적인 메시지 순으로 작성하면, 뷰의 코드 변경없이

오류메시지를 상황에 맞게 출력 할 수 있게된다.

 

< Validator 추출>

 

스프링은 간단한 방법으로 에러처리하는 방법을 제공한다. 

컨트롤러에 @InitBInder 와 함께 WebDataBinder 를 사용하여 사용자 지정 검증 클래스를 지정한다. 

이렇게 되면 @validated 붙은 메서드는 실행시 검증 클래스가 자동으로 실행된다.

사용자 지정 클래스는 스프링이 제공하는 Validator 인터페이스를 구현한다.

support 메서드는 해당 isAssignableFrom 을 통해 Item 클래스의 인스턴스거나 자손 인스턴스 인지 확인한다.

validate 메서드에 원하는 검증로직을 수행하도록 하면 된다. 이때 인자로 Errors (BindingResult 조상) 타입을 받는다.

'프로그래밍 > Spring' 카테고리의 다른 글

[Spring] 로그인 쿠키와 세션  (0) 2024.02.14
[Spring] Bean Validation  (0) 2024.02.12
[Spring] HttpMessageConverter  (0) 2024.02.01
[Spring] Spring 기본기능  (0) 2024.01.30
[Spring] Spring MVC 기본구조  (0) 2024.01.26