Languege/Java & Spring / / 2025. 7. 17. 19:20

[Spring] Java Validation은 어떻게 한글 메시지가 나올까? 배포 중 장애 발생

 

1. 개요

Spring Boot 프로젝트에서 @NotBlank 등 Bean Validation 어노테이션을 사용할 때, 로컬 환경에서는 한글 에러 메시지가 잘 나오지만, 배포(예: Jenkins → AWS EC2) 환경에서는 갑자기 영어 메시지(must not be blank)가 출력되어 당황하신 경험이 있으실 겁니다. 이 글에서는

  1. 왜 로컬과 배포 환경에서 메시지가 다르게 나오는지
  2. 어떻게 한글 메시지를 항상 보장할 수 있는지를 차근차근 살펴보겠습니다.

 

2. 문제 상황 재현

  1. 개발자 PC(macOS, OS 로케일 = ko_KR)
  2. AWS EC2 인스턴스(기본 OS 로케일 = en_US)
  3. 코드에는 어노테이션에 메시지를 따로 지정하지 않음
  4. 배포 파이프라인에서 테스트 코드에 오류 발생
  5. 배포가 안되는 오류 발생

로컬과 배포 환경에서 다른 메시지가 노출되며, 특히 CI/CD 파이프라인 테스트가 깨지는 현상이 발생합니다.

처음에는 git을 잘못 올려서 발생한 문제로 착각해서 캐시를 지우는 등 많은 삽질을 했습니다 ㅎ..

public class MyDTO {
	@NotBlnak //아무런 메시지 설정 X
	private String name;
    ...
}


@Test
@DisplayName("DTO 유효성 검증 - 이름 누락")
void test() {
    // Given
    MyDTO request = MyDTO.builder()
            .name(null)
            .description("Desc")
            .build();

    // When
    ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
    Validator validator = validatorFactory.getValidator();
    Set<ConstraintViolation<ModelSaveRequest>> violations = validator.validate(request);

    // Then
    assertThat(violations).isNotEmpty();

    //여기서 오류 발생!!!
    assertThat(violations).anyMatch(v -> v.getPropertyPath().toString().equals("name") && v.getMessage().equals("공백일 수 없습니다"));
}

3. 원인 분석

3.1 JVM 기본 로케일(Locale.getDefault())

  • 로컬(macOS): OS 로케일이 ko_KR → JVM 기본 로케일도 ko_KR
  • EC2 인스턴스(리눅스): 보통 en_US 로 설치 → JVM 기본 로케일도 en_US
# 로케일 확인
$ locale
LANG=ko_KR.UTF-8        # macOS 예시
LC_ALL=
…
$ locale
LANG=en_US.UTF-8        # EC2 예시
LC_ALL=
…

3.2 Bean Validation 메시지 번들 우선순위

  1. ValidationMessages_{locale}.properties (프로젝트 classpath:/)
  2. 기본 내장 번들 (hibernate-validator 라이브러리 제공 ValidationMessages.properties)

따라서, ValidationMessages_ko.properties 가 없으면 내장 영어 번들(must not be blank)이 사용됩니다.


4. 해결 방법

4.1 ValidationMessages_ko.properties 추가

프로젝트 src/main/resources 폴더에 두 파일을 생성합니다.

  • ValidationMessages.properties
  • javax.validation.constraints.NotBlank.message=This field must not be blank
  • ValidationMessages_ko.properties
  • javax.validation.constraints.NotBlank.message=값을 입력해주세요

이제 JVM 로케일이 ko_KR 일 때는 한글 메시지를, en_US 일 때는 영어 메시지를 각각 읽어옵니다.

4.2 스프링 MessageSource와 Validator 연동

Spring messages_*.properties 파일을 그대로 사용하려면, Validator 빈에 MessageSource 를 연결합니다.

@Configuration
public class ValidationConfig {
  @Bean
  public LocalValidatorFactoryBean validator(MessageSource messageSource) {
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    // 스프링 메시지 소스를 우선 사용
    bean.setValidationMessageSource(messageSource);
    return bean;
  }
}
  • src/main/resources/messages_ko.properties 에도를 추가해 두면, 언제나 스프링 메시지 소스를 통해 한글 메시지를 가져옵니다.
  • javax.validation.constraints.NotBlank.message=값을 입력해주세요

4.3 JVM 옵션으로 로케일 강제 고정

배포 스크립트나 Jenkins 빌드 설정에 JVM 옵션을 추가해, 애플리케이션이 무조건 한국어 로케일을 사용하도록 할 수 있습니다.

java \
  -Duser.language=ko \
  -Duser.country=KR \
  -jar myapp.jar

혹은 파이프라인 내에서:

pipeline {
  environment {
    JAVA_OPTS = '-Duser.language=ko -Duser.country=KR'
  }
  stages {
    stage('Run') {
      steps {
        sh 'java $JAVA_OPTS -jar build/libs/app.jar'
      }
    }
  }
}

5. 결론

테스트 환경과 배포 과정이 다를 수 있지만, 이런 메시지 하나로 오류가 날거라고 생각도 못했습니다.

다른 분들은 저처럼 이런 실수로 시간 낭비를 안하셨으면 좋겠네요.