본문 바로가기

프로그래밍/Spring

[스프링부트] MessageSource를 이용한 다국어 관리

이 글은 오늘 배운 내용을 정리하는 블로그 글 입니다. 


오늘은 스프링부트에서 MessageSource를 이용해서 다국어 관리하는 법을 알아보겠습니다. 

 

MessageSource를 이용하면 resource 파일에 저장된 값을 가져와서 보여줄 수 있습니다. 저희는 resource 파일을 Locale 별로 만들어서 관리할 수 있는데, MessageSource에서 메시지를 가져올 때 Locale 값을 넣어주면 그에 맞는 resource 파일에서 메시지를 가져오게 됩니다. 

 

코드로 한번 보겠습니다. 

예제에서는 간단한게 "hi" 라는 message에 대해서 영어, 한국어, 일본어로 표시해 보겠습니다. 

 

Resource 파일 등록

 

먼저 메시지 정보를 담을 리소스 파일을 만들어 보겠습니다. 

파일명은 'messages.properties' 이름의 파일을 만들고, 그 안에 hi 메시지 정보를 넣어줍니다. 

 

hi = 안녕, {0}

 

안녕 뒤에 '{0}' 값은 이름을 넣어줄 건데, 나중에 MessageSource를 사용할 때 다시 보겠습니다. 

이렇게 만들어진 파일은 기본 메시지 값이 됩니다. 

 

이제 다른 나라 정보를 넣어보겠습니다. 파일명은 아래와 같이 해주세요. 

- 파일명: 'messages_{lang}_{country}.properties' 

- 예, 미국: messages_en.properties 

- 예, 일본: messages_ja_JP.properties 

 

참고로 Country와 Lang 정보는 각각 아래의 페이지를 참고하시면 됩니다. 

- Country: ISO 3166-1 alpha-2

- Lang: ISO 639 alpha-2

- 기타 Local Class Spec.: Link 

 

이렇게 추가적으로 등록한 미국과 일본 메시지 파일 내용입니다. 

 

// 일본
hi = おはよう, {0}

// 미국
hi = Hello, {0}

 

MessageSource를 이용해서 메시지 정보 가져오기

 

이 부분은 AppRunner 클래스를 만들어서, 실행 테스트를 해보겠습니다. 

 

'LocaleAppRunner' 클래스를 만들고, ApplicationRunner를 구현합니다. 

 

@Component
public class LocaleAppRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {

    }
}

 

MessageSource를 정의해야하는데 이미 빈에 등록되어 있기 때문에 'Autowired'로 바로 사용이 가능합니다. 

 

@Autowired
MessageSource messageSource;

 

왜 이렇게 되는 것을 아는게 중요한데요. 바로 ApplicationContext가 이를 구현하고 있기 때문입니다. 

그래서 ApplicationContext로 의존성을 받아서 MessageSource를 사용해도 되고, MessageSource를 명시적으로 선언해주는 것도 가능합니다. 

여기서는 명확하게 보여주기 위해서 MessageSource를 바로 선언했습니다. 

 

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, 
    HierarchicalBeanFactory,
    MessageSource, // 여기에 있습니다
    ApplicationEventPublisher, 
    ResourcePatternResolver {

 

이자 마지막으로 MessageSource를 이용해서, 리소스 정보를 가져오는 부분을 추가해보겠습니다. 

'getMessage()' 메서드를 이용해서 가져올 수 있습니다. 

 

messageSource.getMessage("hi", new String[]{"영철"}, Locale.getDefault())

 

두번째 인자 값인 String[]는 이전에 resource를 선언할 때, 입력했던 '{0}' 값에 바인딩되는 값입니다. 

여기서는 '영철' 을 입력했기 때문에, 이 값이 바인딩 됩니다. 

 

아래는 최종 소스 코드 입니다. 

 

@Component
public class LocaleAppRunner implements ApplicationRunner {

    @Autowired
    MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("Default Locale: " + Locale.getDefault());

        System.out.println("Default");
        System.out.println(messageSource.getMessage("hi", new String[]{"영철"}, Locale.getDefault()));

        System.out.println("중국");
        System.out.println(messageSource.getMessage("hi", new String[]{"영철"}, Locale.CHINA));

        System.out.println("일본");
        System.out.println(messageSource.getMessage("hi", new String[]{"영철"}, Locale.JAPAN));

        System.out.println("미국");
        System.out.println(messageSource.getMessage("hi", new String[]{"영철"}, Locale.US));
    }
}

 

이것을 실행해보면 아래와 같습니다. 

 

Default Locale: ko_KR
Default
안녕, 영철
중국
안녕, 영철
일본
おはよう, 영철
미국
Hello, 영철

 

우선 Default Locale을 출력해 봄으로써 기본 값이 무엇인지 알 수 있습니다. 

저는 'ko_KR'로 나오는데, 제가 한국에 대한 Locale 정보를 구현한게 없기 때문에 Default 가 출력됩니다.  

Locale을 중국으로 했을 때도 동일하게 구현한 Locale이 없기 때문에 Default 가 출력됩니다. 

이와는 다르게 일본이나, 미국으로 Locale을 선언했을 때는 미리 구현된 값이 있기 때문에 그에 맞는 값이 출력 됩니다.