Spring MVC/Validation

Validation 검증 - Message 메시지

Hcode 2022. 12. 9.

 

이전 글로 도메인 객체를 하나만 사용할 때 발생할 수 있는 문제점과 그 해결을 알아보았습니다.
 

Validation 검증 - 도메인 객체를 하나만 사용할 경우 문제점 해결

이전 글로 Bean Validation의 글로벌 Validation 오류에 대해서 알아보았습니다. Validation 검증 - Bean Validation의 글로벌 Validation 오류 이전 글로 Validation을 편하게 할 수 있는 Bean Validation에 대해 알아보았

hhhhicode.tistory.com

이번 글로 검증에 사용될 메시지에 대해 알아보겠습니다.

 


 

메시지

  • FieldError
  • errors.properties

에 대해 다룹니다.

 


 

FieldError

우리가 Bean Validation을 사용한다고 해서 
 FieldError를 직접 다루지 않는 것은 아닙니다.

가끔 이리저리 생각해봐도 그냥 BindingResult에 간단하게 FieldError를 추가하는 게 편하겠구나 하는 상황이 생깁니다.

FieldError의 메시지에 대해 알아보겠습니다.

 

물론 FieldError나 ObjectError를 직접 다루지 않고 BindingResult가 제공하는 rejectValue()와 reject()를 사용하면 편합니다.

해당 부분은 다음 글로 다루겠습니다.

 


 

FieldError 생성자

FieldError는 두 가지 생성자를 제공합니다.

public FieldError(String objectName, String field, String defaultMessage) {
	this(objectName, field, null, false, null, null, defaultMessage);
}

public FieldError(String objectName, String field, @Nullable Object rejectedValue, boolean bindingFailure,
		@Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage) {

	super(objectName, codes, arguments, defaultMessage);
	Assert.notNull(field, "Field must not be null");
	this.field = field;
	this.rejectedValue = rejectedValue;
	this.bindingFailure = bindingFailure;
}
  • objectName : 오류가 발생한 객체 이름
  • field : 오류 필드
  • rejectedValue : 사용자가 입력한 값(거절된 값)
  • bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값
  • codes : 메시지 코드
  • arguments : 메시지에서 사용하는 인자
  • defaultMessage : 기본 오류 메시지

 

FieldError와 ObjectError의 생성자를 보시면
  파라미터에 errorCode와 arguments를 제공합니다.

이 파라미터는 오류 발생 시 errorCode로 메시지를 찾기 위해 사용됩니다.

 

메시지는 어떻게 설정하는지 보았습니다.

FieldError 사용은 앞선 글을 보시면 충분히 나와 있습니다.?...

간단히 말하면

  Validation 오류 발생 시 FieldError를 생성하고 BindingResult에 addError() 합니다.

addError는 ObejctError를 파라미터로 가지고, FieldError는 ObjectError를 상속받으니 인자로 넣을 수 있습니다.

 

그럼 메시지를 어디서 찾는지 알아보겠습니다.

 


 

errors.properties

errors.properties는 MessageSource로 사용되는 것입니다.

MessageSource에 대한 내용은 다음에 다루는 글을 올리겠습니다.

 

  • errors 메시지 파일 생성
  • errors.properties에 메시지 추가
  • errors.properties에 등록한 메시지를 사용

 


 

errors 메시지 파일 생성

messages.properties를 사용해도 됩니다.

이름은 정해져 있지 않습니다.

하지만 일반적인 메시지와 오류 메시지를 구분해주기 위해

  errors.properties를 따로 만들어서 사용합니다.

 

application.properties에서 설정을 해주어야 할 것이 있습니다.

메시지 파일을 사용할 것이라는 명시를 해주어야 합니다.

spring.messages.basename=messages, errors

설정에서 이름부터 messages인게 메시지 관련 설정인 냄새가 폴폴 납니다.

해당 설정을 하고 메시지를 재사용할 때면 짜릿합니다.

막 뭔가 코딩 잘하는거같고... 느낌 있습니다.

낭만 있어요.

개인적으로 3번 이상 반복되는 메시지라면 messages.properties나 errors.properties에 등록해버립니다.

 


 

errors.properties에 메시지 추가

errors.properties에 추가된 메시지의 예를 보겠습니다.

required.item.itemName=상품 이름은 필수입니다.
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
max.item.quantity=수량은 최대 {0} 까지 허용합니다.
totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}

required.member.userName=이름은 필수입니다.
range.member.password=비밀번호는 {0} 자리 이상 {1} 자리 이하여야 합니다.
range.member.memo=메모는 1000자 이하여야 합니다.

국제화 기능을 사용하고 싶으면

  errors_en.properties를 생성해서 해당 언어로 메시지를 작성하여 사용하시면 됩니다.

 

 


 

errors.properties에 등록한 메시지 사용

errors.properties에 등록한 메시지를 사용하도록 해봅시다.

 

제가 하고 있는 개인 프로젝트에서 예시를 들어보겠습니다.

 

errors.properties

exist.memberAddDto.userId=이미 존재하는 Id 입니다.
@ResponseBody
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
public Member add(@Validated @RequestBody MemberAddDto memberAddDto, BindingResult bindingResult) {

    //Validation
    Optional<Member> findMember = memberService.findByUserId(memberAddDto.getUserId());
    if (findMember.isPresent()) {
        bindingResult.addError(new FieldError("memberAddDto", "userId",
                memberAddDto.getUserId(), false, new String[]{"exist.memberAddDto.userId"}, null, null));
    }
    ...

    //Validation Pass Logic
    ...
}

회원가입 시 userId가 존재하는지 확인 후
  존재한다면 userId로 FieldError를 생성하고

    BindingResult 객체에 담습니다.

그리고 해당 BindingResult는 View에서 사용됩니다.

 


 

codes

errors.properties를 보니 'exist.memberAddDto.userId=이미 존재하는 Id입니다.'가 있습니다.

errors.properties에서
  exist.memberAddDto.userId로 찾아서 메시지 코드를 지정합니다.

 

메시지 코드는 하나가 아니라 배열로 여러 값을 전달할 수 있는데
  순서대로 매칭 해서 처음 매칭 되는 메시지를 사용합니다.

new String []{"exist.memberAddDto.userId", "exist.default"}가 있으면

  exist.memberAddDto.userId를 먼저 찾아봅니다.

해당 배열에서 매칭 되는 codes가 없으면

  defaultMessage를 출력합니다.

맨 마지막 파라미터로 @Nullable String defaultMessage를 찾을 수 있으실 겁니다.

 


 

arguments

new Object []{1000, 10000}을 사용해서
  messages의 {0}, {1}에 치환할 값을 전달할 수 있습니다.

@Nullable Object[] arguments 입니다. 저는 null을 사용했습니다.

 


 

다음 글로  BindingResult의 rejectValue와 reject에 대해 알아봅시다.
 

Validation 검증 - BindingResult의 rejectValue와 reject

이전 글로 Validation에 메시지를 사용하는 간단한 내용을 보았습니다. Validation 검증 - Message 메시지 이전 글로 도메인 객체를 하나만 사용할 때 발생할 수 있는 문제점과 그 해결을 알아보았습니다

hhhhicode.tistory.com

댓글