🍀 Spring
Spring 메시지, 국제화
다양한 메시지를 한 곳에서 관리하도록 하는 기능
목적
상품명이라는 단어를 모두 상품이름으로 고쳐달라고 하면 어떻게 해야할까?
메시지
messages.properties
라는 메시지 관리용 파일을 만들고item=상품 item.id=상품 ID item.itemName=상품명 item.price=가격 item.quantity=수량
각 HTML들은 다음과 같이 해당 데이터를 key 값으로 불러서 사용
addForm.html
<label for="itemName" th:text="#{item.itemName}"></label>
국제화
메시지에서 설명한 메시지 파일(
messages.properties
)을 각 나라별로 별도로 관리하면 서비스를 국제화 할 수 있다.messages_ko.properties
item=상품 item.id=상품 ID item.itemName=상품명 item.price=가격 item.quantity=수량
messages_en.properties
item=Item item.id=Item ID item.itemName=Item Name item.price=price item.quantity=quantity
한국에서 접근한 것인지 영어에서 접근한 것인지는 인식하는 방법은 HTTP accept-language 해더 값을 사용하거나 사용자가 직접 언어를 선택하도록 하고, 쿠키 등을 사용해서 처리하면 된다.
메시지와 국제화 기능을 직접 구현할 수도 있겠지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공한다.
그리고 타임리프도 스프링이 제공하는 메시지와 국제화 기능을 편리하게 통합해서 제공한다.
Spring 메시지 소스 설정
메시지 관리 기능을 사용하려면 스프링이 제공하는
MessageSource
를 스프링 빈으로 등록하면 되는데, MessageSource
는 인터페이스이다. 따라서 구현체인 ResourceBundleMessageSource
를 스프링 빈으로 등록하면 된다.직접 등록
@Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasenames("messages", "errors"); messageSource.setDefaultEncoding("utf-8"); return messageSource; }
basenames
: 설정 파일의 이름을 지정한다.messages
로 지정하면messages.properties
파일을 읽어서 사용한다.- 추가로 국제화 기능을 적용하려면
messages_en.properties
,messages_ko.properties
와 같이 파일명 마지막에 언어 정보를 주면된다. - 만약 찾을 수 있는 국제화 파일이 없으면
messages.properties
(언어정보가 없는 파일명)를 기본으로 사용한다. - 파일의 위치는
/resources/messages.properties
- 여러 파일을 한번에 지정할 수 있다. 여기서는
messages
,errors
둘을 지정했다.
defaultEncoding
: 인코딩 정보를 지정한다. utf-8 을 사용하면 된다.
Spring Boot
스프링 부트를 사용하면 스프링 부트가
MessageSource
를 자동으로 스프링 빈으로 등록한다.application.properties
spring.messages.basename=messages,config.i18n.messages
메시지 소스 기본 값
spring.messages.basename=messages
MessageSource
를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages
라는 이름으로 기본 등록된다. 따라서 messages_en.properties
, messages_ko.properties
, messages.properties
파일만 등록하면 자동으로 인식된다.메시지 파일 만들기
메시지 파일을 만들어보자.
국제화 테스트를 위해서
messages_en
파일도 추가하자.messages.properties
:기본 값으로 사용(한글)
messages_en.properties
: 영어 국제화 사용
주의! 파일명은 massage가 아니라 messages다! 마지막 s에 주의하자
/resources/messages.properties
messages.properties
hello=안녕 hello.name=안녕 {0}
/resources/messages_en.properties
messages_en.properties
hello=hello hello.name=hello {0}
스프링 메시지 소스 사용
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;
MessageSource
인터페이스를 보면 코드를 포함한 일부 파라미터로 메시지를 읽어오는 기능을 제공한다.메시지 사용
ms.getMessage("hello", null, null);
- code:
hello
- args:
null
- locale:
null
locale
정보가 없으면basename
에서 설정한 기본 이름 메시지 파일을 조회
basename
으로messages
를 지정 했으므로messages.properties
파일에서 데이터 조회
기본 메시지
- 메시지가 없는 경우에는
NoSuchMessageException
이 발생한다.
- 메시지가 없어도 기본 메시지(
defaultMessage
)를 사용하면 기본 메시지가 반환된다.
매개변수 사용
ms.getMessage("hello.name", new Object[]{"Spring"}, null);
다음 메시지의 {0} 부분은 매개변수를 전달해서 치환할 수 있다.
hello.name=안녕 {0}
→ Spring 단어를 매개변수로 전달 → 안녕 Spring
국제화 파일 선택
- locale 정보를 기반으로 국제화 파일을 선택
- Locale이 en_US 의 경우
messages_en_US
→messages_en messages
→messages
순서로 찾는다.
Locale
에 맞추어 구체적인 것이 있으면 구체적인 것을 찾고, 없으면 디폴트를 찾는다고 이해하면 된다.
국제화 사용
ms.getMessage("hello", null, null);
: locale 정보가 없는 경우Locale.getDefault()
을 호출해서 시스템의 기본 로케일을 사용 예)locale = null
인 경우 시스템 기본locale
이ko_KR
이므로messages_ko.properties
조회 시도 → 조회 실패 →messages.properties
조회
ms.getMessage("hello", null, Locale.KOREA);
: locale 정보가 있지만,message_ko
가 없으므로messages
를 사용
ms.getMessage("hello", null, Locale.ENGLISH);
: locale 정보가Locale.ENGLISH
이므로messages_en
을 찾아서 사용
Thymeleaf
메시지 적용
- 타임리프의 메시지 표현식
#{...}
를 사용하면 스프링의 메시지를 편리하게 조회
- 등록한 상품이라는 이름을 조회하려면
#{label.item}
국제화 선택
Spring은 언어 선택시 기본으로
Accept-Language
헤더의 값을 사용한다.LocaleResolver
스프링은
Locale
선택 방식을 변경할 수 있도록 LocaleResolver
라는 인터페이스를 제공하는데, 스프링 부트는 기본으로 Accept-Language
를 활용하는 AcceptHeaderLocaleResolver
를 사용한다.public interface LocaleResolver { Locale resolveLocale(HttpServletRequest request); void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale); }
LocaleResolver 변경
LocaleResolver
의 구현체를 변경해서 쿠키나 세션 기반의 Locale
선택 기능을 사용할 수 있다. 예를 들어, 고객이 직접 Locale 을 선택하도록 하는 것이다. 관련해서 LocaleResolver
를 검색하면 수 많은 예제가 나오니 필요한 분들은 참고하자.