MessageSource
public interface MessageSource {
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
국제화(i18n) 및 지역화(l10n)를 위한 메시지 관리 인터페이스(spring core)
동작 과정
- 미리 메시지 소스 파일에 메시지 코드와 그에 대응하는 메시지를 키-값으로 정의
- 메시지 소스 파일은 Locale별로 구성 가능
- 각 메시지 소스 파일에 로케일 정보를 포함시키면 됨(messages_en.properties, messages_ko.properties)
- MessageSource를 스프링 컨텍스트에 등록
- 스프링 부트의 auto-configuration으로 인해 자동 등록되고 메시지 소스 파일의 이름이 “messages”로 설정됨
- 추가적으로 메시지 소스 파일 이름을 정의하려면
spring.messages.basename
속성에 지정
- MessageSource.getMessage()를 통해 메시지 소스 파일에 정의된 메시지를 읽어옴
- 이 때 code, args, defaultMessage, locale 정보를 파라미터로 받음
MessageSource 구현체
- ResourceBundleMessageSource : 메시지 소스 파일(.properties)에서 메시지를 로드
- ReloadResourceBundleMessageSource : 애플리케이션 실행 중 메시지 소스 파일의 변경 사항 반영, 캐싱 기간 설정 가능
- StaticMessageSource : 테스트용 MessageSource
MessageCodesResolver
public interface MessageCodesResolver {
String[] resolveMessageCodes(String errorCode, String objectName);
String[] resolveMessageCodes(String errorCode, String objectName, String field, @Nullable Class<?> fieldType);
}
데이터 바인딩 및 검증 과정에서 발생하는 에러 코드(ObjectError, FieldError)를 메시지 코드로 변환하는 인터페이스
변환된 메시지 코드를 MessageSource를 통해 메시지를 읽어옴
MessageCodesResolver 구현체
DefaultMessageCodesResolver : 특정 필드에 대한 오류 코드를 바탕으로 메시지 코드 생성
DefaultMessageCodesResolver 동작 방식(아래의 순서로 메시지 코드 변환)
- 객체 이름과 필드 이름을 포함한 코드(simpleUser.email.required)
- 필드 이름만 포함한 코드(email.required)
- 객체 이름만 포함한 코드(simpleUser.required)
- 글로벌 코드(required)
BindingResult 또는 Errors 인터페이스와 함께 동작
LocaleResolver
현재 요청의 Locale을 결정하는 객체
MessageSource와 함께 동작하며 결정된 Locale에 맞는 메시지 제공
LocaleResolver구현체
- FixedLocaleResolver
- AcceptHeaderLocaleResolver
- SessionLocaleResolver
- CookieLocaleResolver
LocalChangeInterceptor
- HTTP Request의 특정 파라미터를 기반으로 Locale을 변경할 수 있는 Interceptor
ErrorResponse + MessageSource
MessageSource는 bean validation, spring mvc 표준 예외에 대한 메시지를 처리하는 데 사용되는 경우가 많았음
spring 6.0 부터 추가된 ErrorResponse를 통해 예외 메시지를 처리할 수 있음
// ErrorResponse
default ProblemDetail updateAndGetBody(@Nullable MessageSource messageSource, Locale locale) {
if (messageSource != null) {
String type = messageSource.getMessage(getTypeMessageCode(), null, null, locale);
if (type != null) {
getBody().setType(URI.create(type));
}
Object[] arguments = getDetailMessageArguments(messageSource, locale);
String detail = messageSource.getMessage(getDetailMessageCode(), arguments, null, locale);
if (detail != null) {
getBody().setDetail(detail);
}
String title = messageSource.getMessage(getTitleMessageCode(), null, null, locale);
if (title != null) {
getBody().setTitle(title);
}
}
return getBody();
}
updateAndGetBody()는 예외 타입, argument, detail message code를 기반으로 MessageSource를 통해 메시지로 변환한 뒤
각각 ProblemDetail의 type, detail, title로 설정하는 메서드임
근데 사실 ProblemDetail은 MessageSource를 사용하지 않고도 직접 예외 메시지를 처리할 수 있기 때문에 편한 방법으로 사용하면 되지 않을까 싶기도 하고