Spring/Spring MVC - 활용

메시지, 국제화

진이최고다 2023. 9. 3. 23:58

메시지 / 국제화

메시지 

기획자가 화면에 보이는 문구 중 "상품명" 단어를 "상품 이름" 으로 바꾸고 싶어한다면 ? 각 화면에서 이 단어를 일일이 변경해야 한다. 화면이 많아질수록 변경해야하는 파일의 수도 기하급수적으로 늘어날 것이고, 이는 비 효율적이다.

 

해결 방법

이러한 문제를 해결하기 위해 메시지 기능을 사용할 수 있다. 메시지 기능은 다양한 메시지(문구)를 한 곳에서 통합적으로 관리할 수 있다.

예시 : message.properties - 메시지 관리 파일 생성한다
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

각 HTML 파일에서는 해당 데이터를 key 값으로 불러와 사용한다.

addForm.html: <label for="itemName" th:text="#{item.itemName}"></label>
editForm.html: <label for="itemName" th:text="#{item.itemName}"></label>

국제화

국제화는 서비스나 제품을 다양한 언와 문화에 맞게 적용하는 것을 의미한다. 각 나라별로 별도의 메시지 파일을 관리하여 서비스를 국제화 할 수 있다.

messages_en.properties (영어 버전):
item=Item
item.id=Item ID
item.itemName=Item Name
item.price=Price
item.quantity=Quantity

messages_ko.properties (한국어 버전):
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

사용자 언어 인식

한국에서 접근한 것인지, 영어권에서 접근한 것인지 인식하는 방법은 HTTP accept-language 헤더 값을 사용하거나 사용자가 직접 언어를 선택하게 할 수 있다. 선택한 언어 정보는 쿠키 등의 방법으로 저장되어 사용된다.

 

프레임워크 지원

스프링은 메시지 및 국제화 기능을 기본적으로 제공한다. 추가적으로 뷰 템플릿 타임리프도 스프링이 제공하는 메시지 및 국제화 기능을 통합하여 제공한다.


스프링 메시지 소스 설정

스프링은 메시지 관리 기능을 통해 다국어 처리 및 메시지를 중앙에서 관리할 수 있게 해준다. 이를 위해 "MessageSource" 인터페이스와 그 구현체인 "ResourceBundleMessageSource"를 제공한다.

 

스프링 MessageSource 스프링 빈 등록
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("messages", "errors");
    messageSource.setDefaultEncoding("utf-8");
    return messageSource;
}

setBasenames : 메시지 소스 파일의 기본 이름을 설정한다. 예를 들어 "message"로 설정하면, "message.propertice" 파일을 읽게 된다.

이를 통해 "message_en.properties, message_ko.properties" 와 같이 국제화 기능을 적용할 수 있다.

 

스프링 부트 MessageSource 스프링 빈 등록

스프링 부트를 사용할 경우 "MessageSource" 가 자동으로 빈으로 등록된다. 따라서 별도의 설정이 필요 없이 "application.properties" 파일에서 속성만 설정하면 된다.

 

스프링 부트의 기본 설정값

spring.messages.basename=messages

즉, 별도의 설정 없이 "message.properties", "message_en.properties" 등의 파일을 만들면 스프링 부트가 자동으로 인식한다.

 


스프링 메시지 소스 사용

스프링에서 제공하는 MessageSource 인터페이스는 애플리케이션에서 국제화(i18n) 및 로컬화(l10n) 기능을 지원하기 위한 메시지 소스를 관리한다. 이 인터페이스를 사용하면 다양한 언어로 지정된 메시지를 쉽게 가져올 수 있다.

 

MessageSource 인터페이스 
	public interface MessageSource {
		String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
		String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

1. String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);

  • 지정된 code 로 메시지를 찾아서 반환한다.
  • 만약 해당 코드로 메시지를 찾을수 없을 경우 'defaultMessage' 가 반환된다.
  • 'args' 는 메시지 내부에서 사용될 파라미터로 배열로, 메시지에 포함된 플레이스홀더를 대체하는데 사용된다.
  • 'locale' 은 특정 언어 및 지역 설정을 나타내며, 해당 로케일에 맞는 메시지를 가져온다.

 

2. String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;

  • 지정된 code 로 메시지를 찾아서 반환한다.
  • 하지만 해당 코드로 메시지를 찾을 수 없을 경우 'NoSuchMessageException' 예외가 발생한다.
messages.properties 메시지 정의
hello=안녕
hello.name=안녕 {0}

다음과 같이 'MessageSource' 를 사용하여 메시지를 가져올 수 있다.

@Autowired
MessageSource ms;

@Test
void argumentMessage() {
    String message = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
    assertThat(message).isEqualTo("안녕 Spring");
}

 

국제화 파일 선택

locale 정보 기반으로 국제화 파일을 선택한다.

  • Locale이 en_US의 경우 message_en_US -> message_en -> message 순서로 찾는다.
  • Locale에 맞추어 구체적인 것이 있으면 구체적인 것을 찾고, 없으면 dafault 값으로 찾는다.

웹 애플리케이션 메시지,국제화 적용 


타임리프 메시지 적용

타임리프의 메시지 표현식 #{} 를 사용하여, 스프링 메시지를 조회할 수 있다. 예를 들어 'label.item' 메시지를 조회하려면 #{label.item} 을 사용한다.

렌더링 전
<div th:text="#{label.item}"></div>
렌더링 후
//Locale.KR
<div>상품</div>

//Locale.ENGLISH
<div>Item</div>
타임리프 템플릿 메시지 적용
<h2 th:text="#{page.addItem}">상품 등록</h2>
...
<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
...

스프링의 국제화 메시지 선택

웹 브라우저의 언어 설정 값을 변경하면 요청시 Accept-Language 의 값이 변경된다.

스프링은 Loacle 정보를 Accpet - Longuage 헤더 기반으로 언어를 선택한다.


LocaleResolver 

스프링은 LocaleResolver 인터페이스를 통해 언어 선택 방법을 제공한다. 스프링 부트는 기본적으로 AcceptHeaderLocaleResolver 를 사용하여 'Accept - Language' 헤더 값을 활용 한다. 

LocaleResolver 인터페이스
public interface LocaleResolver {
    Locale resolveLocale(HttpServletRequest request);
    void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}

LocaleResolver 변경

구현을 변경하면 언어 선택 방법도 변경할 수 있다. 예를 들어, 쿠키나 세션 기반의 언어 선택 방법을 사용할 수 있다. 또한 사용자가 직접 언어를 선택할 수 있게 하는 방법도 구현할 수 있다.

 

결론적으로 스프링에서 국제화를 구현하기 위해서는 메시지 소스의 설정, 웹 브라우저의 언어 설정 변경 'LocaleResolver' 의 활용 및 변경 등의 방법이 있으며, 원하는 방법을 통해 국제화를 적용은 물론, 적절한 메시지와 리소스를 제공할 수 있다.