스프링 스터디 ; 메시지, 국제화

MINJU·2022년 3월 20일
0

스프링

목록 보기
7/15
post-thumbnail
post-custom-banner

메시지, 국제화 소개

: '상품목록', '상품명' 등과 같은 레이블을 바꾸고 싶다면, 각 html에 하나하나 들어가서 텍스트를 수정하는 방법을 사용해야만했을 것입니다.

: 스프링은 이에 대한 보다 유동적인 처리를 위하여 메시지 기능을 제공합니다

: 또한, 내가 영어권 사용자이면 'list', 'name'으로 표시될 수 있게끔하는 국제화 기능도 제공합니다.

: 이번 장에서는 앞서 언급한 메시지 기능, 국제화 기능에 대해 구체적으로 다뤄보려고 한다.


스프링 메시지 소스 설정

: 스프링부트를 사용하면 메시지 관리 기능을 제공하는 MessageSource 를 자동으로 스프링 빈으로 등록해줍니다.
: 이때 MessageSource 인터페이스의 내용은 다음과 같습니다.

public interface MessageSource{
	// default 메시지 정의 가능
	@Nullable
    String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
    
    // 기본 코드
    String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
    
    // MessageSourceResolvable 재정의 가능
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
    

: 스프링부트를 사용하지 않는다면 직접 등록해야만하는데 방법은 다음과 같다. 이 예제는 MessageSource 인터페이스의 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하는 예제입니다.

@Bean
public MessageSource messageSource(){
	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenmaes("messages", "errors");
    // basenames 세팅을 통해 설정 파일의 이름을 지정합니다.
    // messages로 지정했으므로 -> messages.properties 파일을 읽습니다.
    // 추가로 국제화 기능을 적용하려면 파일명 마지막에 언어정보를 주면 됩니다. ex) messages_en.properties.. 
    // 국제화 파일이 없으면 messgaes.properties를 기본으로 사용합니다.
    // 여러 파일을 한 번에 지정할 수도 있습니다. 위에서는 messages, errors 둘을 지정했습니다.
    messageSource.setDefaultEncoding("utf-8");
    return messageSource;
}



+) 추가로 ResourceBundleMessageSource 클래스에 대해 찾아보았습니다.

무언가 굉장히 복잡해보이지만 결국 예제에서 사용한 생성자 코드는

다음과 같음을 확인할 수 있었습니다.




스프링 부트 메시지 소스 설정

: application.properties에 다음과 같이 메시지 소스를 설정할 수 있습니다.
spring.messages.basename=messages, config.i18n.messages

config.i18n.messages 은 국제화를 위한 소스이다.

: 설정파일의 폴더 구조는 다음과 같다.

: 아래 예제에서 계속 사용할 properties는 다음과 같다.





스프링 메시지 소스 사용


MessageSource ms;
ms.getMessage("hello", null, null);

해당 코드의 결과물로는 mesages.properties의 hello 값에 해당하는 "안녕"을 불러온다. locale정보가 없으면 basename에서 설정한 기본 이름 메시지 파일을 조회하기 때문이다. 기본 메시지도 없으면 해당 코드는 NoSuchMessageException 에러를 반환한다.

MessageSource ms;
ms.getMessage("no_code", null, "기본 메시지", null);

결과로는 "기본 메시지"가 출력된다. no_code라는 키 값을 기본 properties 파일에서 찾을 수 없기 때문이다.

MessageSource ms;
ms.getMessage("hello.name", new Object[]{"Spring!"}, null);

결과로는 "안녕 Spring!"이 출력된다. properties의 {0} 부분은 치환될 수 있고, 치환하기 위해서는 args에 Object 배열로서 값을 전달해주면 되기 때문이다.

ms.getMessage("hello", null, Locale.KOREA));

결과로는 "안녕"이 나온다. locale 정보가 있지만, messages_ko가 없으므로 기본 properties가 나오는 것이다.

ms.getMessage("hello",null, Locale.ENGLISH);

결과로는 "hello"가 나온다. messages_en 설정파일을 사용하기 때문이다.



타임리프 메시지 적용

타임리프의 메시지 표현식을 사용하면 스프링 메시지를 편리하게 조회할 수 있습니다.
<div th:text="#{label.item}">
: 이런 방식을 사용하면 보다 쉽게 국제화 기능을 적용할 수 있게 됩니다.



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

: 스프링은 언어 선택시 기본으로 Accept-Language 헤더의 값을 사용합니다.
: 이때 스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver라는 인터페이스를 제공합니다.
: 스프링부트는 기본적으로 Accept-Language를 활용하는 AcceptHeaderLocaleResolver를 사용합니다.

: 이때 LocalResolver 인터페이스는

public interface LocaleResolver {
	Locale resolveLocale(HttpServletRequest request);
	void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);

다음과 같습니다.




(추가) LocaleResolver

참조

AcceptHeaderLocaleResolver

: 디폴트 설정값인 AcceptHeaderLocaleResolver입니다.
: 해당 resolver를 사용하면 웹 브라우저의 locale 정보(Accept Language)에 따라 application의 locale 정보를 지정하게 됩니다.
: 메시지만 다국어로 분기했을 뿐, 아무것도 처리하지 않은 환경에서 사용하기 적합합니다.

SessionLocaleResolver

: 실제로 많이 사용되는 localeResolver입니다.
: 말 그대로 Session에 Locale 정보를 박아넣고 이를 통해 다국어를 처리해주는 역할을 한다고 봅니다.
: 처음 들어갈때는 AcceptHeaderLocaleResolver처럼 브라우저의 언어 설정에 의한 Accept-Language로 값이 결정되는데 단, setDefaultLocale을 설정한다면 이 값이 최우선이 됩니다. 이는 세션으로 저장되며 org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE이라는 세션 속성 이름으로 클래스를 시리얼라이징 되어 저장합니다.
: LocaleResolver에 대해 설정을 넣는 방법은 다음과 같습니다.

: Config 파일에서 LocaleResolver에 대한 설정을 넣습니다.

@Bean
public SessionLocaleResolver localeResolver(){
	SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
    sessionLocaleResolver.setDefaultLocale(new Locale("ko"));
    // 기본 언어로 Ko를 설정.
    return sessionLocaleResolver;

: session에 화면으로부터 넘어온 language라는 param 값으로 locale을 setting해줍니다. 이를 위한 컨트롤러 설정은 다음과 같스니다.

@RequestMapping(value="/changeLocale")
public void changeLocale(String language, HttpSession session){
	session.setAttribute(SessionLocaleResolver.LOCLAE_SESSION_ATTRIBUTE_NAME, new Locale(language));
    }



CookieLocaleResolver

: 쿠기를 이용해서 Locale 정보를 담는 것입니다.
: setLocale()을 통해 Locale 정보를 담은 Cookie를 생성하고 resolveLocale()에서는 Cookie로부터 Locale 정보를 가지고 옵니다.

: 설정은 다음과 같습니다.

@Bean
public LocaleResolver localeResolver(){
	CookieLocaleResolver localeResolver = new CookieLocaleResolver();
    localeResolver.setCookieName("lang");
    localeResolver.setDefaultLocale(new Locale("ko"));
    localeResolver.setCookieHttpOnly(true);
    return localeResolver;
}

: setLocale로 Cookie에 담을 수 있으며

@Autowired
LocaleResolver localeResolver;

@RequestMapping(value="/changeLocale")
public void changeLocale(String language, HttpServletRequest request, HttpServletResponse response){
	Locale locale = new Locale(language);
    localeResolver.setLocale(request, response, locale);

: resolverLocale을 사용해서 Cookie에 담긴 locale 정보를 가지고 올 수도 있다.

public static Locale getLocale(HttpServletRequest request){
	Locale locale = localeResolver.resolveLocale(request);
    return (locale != null)?(Locale)locale:getDefaultLocale();
}
post-custom-banner

0개의 댓글