Spring + Hibernate Validator Custom Message

2020. 9. 15. 17:27Java/Spring

Java Bean Validation

일반적으로 데이터 검증(Validation)은 여러 계층에 걸쳐서 이루어지게 됩니다. 거의 동일한 내용의 검증 로직이 각 계층별로 구현된다면 그것은 중복이고 낭비가 심한 작업입니다. 또한 그러한 경우 각 계층별로 구현된 검증 로직간 불일치로 인해 오류가 발생하기도 쉽습니다. 이를 해결하기 위해 데이터 검증을 위한 로직을 도메인 모델 자체에 묶어서 표현하는 방법이 있습니다. 실제 코드로 표현된다면 너무 장황하고 복잡하기 때문에, Java에서는 Bean Validation이라는 이름으로 Annotation을 데이터 검증을 위한 메타 데이터로 사용하는 방법을 제시하고 있습니다.

Hibernate Validator
Hibernate Validator는 Bean Validation 명세에 대한 구현체입니다.

Spring + Hibernate Validator에서 Custom Message를 작성하는 법

public class User {

    @NotNull
    private String userId;
}

우선 예를 들어 위와 같이 존재하는 모델 클래스가 있습니다. 만약 User 객체를 생성할 때, userId 데이터가 Null로 들어오게 되면 validation 검증으로 인해 Exception이 발생하고 "must not be null"과 같은 메시지가 반환됩니다. 하지만 이 메시지만으로는 어떠한 Field에 null이 들어간건지 알 수 없습니다. 그래서 좀 더 명확하게 메시지를 전달하기 위해 다음과 같은 방법으로 custom message를 작성합니다.

public class User {

    @NotNull(message = "userId must not be null")
    private String userId;
}

이와 같이 작성하면 message가 "userId must not be null"과 같이 반환됩니다. 하지만 이러한 경우에도 문제가 존재합니다. 다수의 validation annotation에 message를 직접 설정해주면 모델 클래스가 지저분해 진다는 것입니다. 그래서 일반적으로 문자열 데이터를 저장하는데 사용할 수 있는 .properties 파일을 이용해 데이터를 저장하고 가져올 수 있습니다. 메시지를 properties 파일에 저장하고 가져오는 방법은 다음과 같습니다. 우선 main/resources/message.properties파일을 생성해 줍니다.

# message.properties
user.id.notnull=userId must not be null

그리고 WebMvcConfigurer를 구현한 클래스에 다음과 같이 작성해줍니다.

public class WebConfig implements WebMvcConfigurer {

    ...

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:/message");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource());
        return bean;
    }
}

properties 파일로부터 메시지 문자열 데이터를 읽어올 ReloadableResourceBundleMessageSource 구현체를 빈으로 정의해 줍니다. 그리고 getValidator를 Override하여 메시지 소스를 가진 객체를 직접 지정해줍니다. 이와 같이 설정하면 다음과 같이 간단하게 메시지 내용을 정의해줄 수 있습니다.

public class User {

    @NotNull(message = "{user.id.notnull}")
    private String userId;
}
728x90

'Java > Spring' 카테고리의 다른 글

Spring MVC와 WebFlux의 차이  (0) 2021.10.29
Spring Batch Chunk 지향 처리  (0) 2021.03.22
Spring Integration  (0) 2020.09.15
Spring WebFlux  (0) 2020.09.13
Spring boot 와 Spring Legacy 비교  (0) 2020.09.10