[Spring] Spring 어플리케이션 메시지 다국어 및 재로딩 처리

2021. 4. 21. 02:07 Spring Framework/Spring Core

[Spring] Spring 어플리케이션 메시지 다국어 및 재로딩 처리

Spring IoC 컨테이너 = ApplicationContext가 갖고있는 기능 중 MessageSource는 국제화(i18n)와 관련된 기능을 제공해주는데 이를 이용해서 어플리케이션에서 출력하는 메시지를 다국화할 수 있다.

 

1. 메시지 파일 작성

resources 디렉토리 아래에 messages.properties, messages_ko_KR.properties 파일을 새로 생성한다.

여기에 어플리케이션에서 출력할 메시지를 messages.properties에는 영어로, messages_ko_KR.proeprties에는 한국어로 작성할 것이다.

파일명에 오타가 나지 않도록 조심하자.

파일을 생성하고 나면 자동으로 'messages'라는 이름의 resource bundle로 묶인다.

 

messages.properties와 messages_en_US.properties에는 greeting=Hello, {0}를, messages_ko_KR.properties에는 greeting=안녕, {0}을 작성한다.

{0}은 넘어온 argument가 바인딩될 부분이다.

 

2. 메시지 빈 등록

1) Spring Boot를 사용하지 않는 경우

Spring boot를 사용하지 않으면 메시지를 빈으로 직접 등록해야 한다.

@Bean
public MessageSource messageSource() {
    var messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages");
    messageSource.setDefaultEncoding("UTF-8");
 
    return messageSource;
}

 

var는 Java 10 이상부터 지원되므로 10 미만이라면 MessageSource 인스턴스를 ResourceBundleMessageSource 타입으로 생성해준다.

setBasename() 메소드로 메시지 리소스 번들을 지정하고 한글이 깨지지 않도록 setDefaultEncoding() 메소드로 문자 집합을 설정한다.

 

2) Spring Boot를 사용하는 경우

Spring boot 기반의 프로젝트일 경우 ResourceBundleMessageSource가 자동으로 빈으로 등록이 되고 이 빈이 messages 리소스 번들을 메시지 소스로 읽어온다.

따라서 빈을 등록하지 않고 바로 사용할 수 있다.

 

3. 메시지 출력

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
 
import java.util.Locale;
 
@Component
public class AppRunner implements ApplicationRunner {
 
    @Autowired
    MessageSource messageSource;
 
    @Override
    public void run(ApplicationArguments args) throws Exception {
       Locale.setDefault(Locale.ROOT);
        System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.getDefault()));
        System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.US));
        System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.KOREA));
    }
}

MessageSource 객체를 주입받고 getMessage()로 메시지를 출력한다.

getMessage()의 첫 번째 파라미터는 메시지 프로퍼티의 key, 두 번째 파라미터는 메시지 출력 시 전달할 argument, 세 번째 파라미터는 Locale을 설정한다.

 

실행 결과

첫 번째 출력문은 messages.properties의 메시지를,

두 번째 출력문은 messages_en_US.properties의 메시지를,

세 번째 출력문은 messages_ko_KR.properties의 메시지를 출력한다.

 

4. 어플리케이션 실행 중에 메시지 리소스 Reload 하기

MessageSource의 구현체를 ResourceBundleMessageSource가 아닌 ReloadableResourceBundleMessageSource를 사용하면 어플리케이션 실행 중에 메시지 리소스 변경을 reload하게 하여 변경사항을 적용할 수 있다.

 

MessageSource 빈을 다음과 같이 정의한다.

@Bean
public MessageSource messageSource() {
    var messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename("classpath:/messages");
    messageSource.setDefaultEncoding("UTF-8");
    messageSource.setCacheSeconds(3);
 
    return messageSource;
}

 

ResourceBundleMessageSource로 생성할때와 달리 ReloadableResourceBundleMessageSource를 사용할때는 setBasename()에 "classpath:/messages" 형식으로 basename을 설정해야한다.

setCacheSeconds()로 메시지 소스를 캐시하는 최대 시간(초)를 설정한다.

위와 같이 설정하면 3초까지는 캐싱하고 3초가 지나면 메시지를 다시 읽는다.

while (true) {
    System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.getDefault()));
    System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.US));
    System.out.println(messageSource.getMessage("greeting", new String[]{"Leica"}, Locale.KOREA));
 
    Thread.sleep(1000l);
}

 

메시지 출력 코드를 while로 감싸고 Thread.sleep()을 호출하여 1초에 한번씩 메시지를 읽어 출력하도록 변경한다.

 

ReloadableResourceBundleMessageSource로 MessageSource 빈을 생성했기 때문에 이제 실행 중에 메시지 변경이 가능하다.

 

어플리케이션을 실행하고 while문이 돌면서 메시지를 출력하는 동안 메시지 내용을 바꾸고 build해보자.

바뀐 메시지가 적용될 것이다.

 

실행 결과

 

References

인프런 - 백기선님의 스프링 프레임워크 핵심 기술

 

출처 : atoz-develop.tistory.com/entry/Spring-Spring-%EC%96%B4%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%A9%94%EC%8B%9C%EC%A7%80-%EB%8B%A4%EA%B5%AD%EC%96%B4-%EB%B0%8F-%EC%9E%AC%EB%A1%9C%EB%94%A9-%EC%B2%98%EB%A6%AC?category=869243