스프링 핵심 기술-06.MessageSource


IoC 컨테이너 7부 : MessageSource

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}

역시 마찬가지로 ApplicationContext가 상속받고 있는 구현체입니다.

MessageSource

  • 국제화 (i18n) 기능을 제공하는 인터페이스. (다국어)
  • ApplicationContext extends MessageSource
    • getMessage(String code, Object[] args, String, default, Locale, loc)

스프링 부트를 사용한다면 별다른 설정 필요없이 messages.properties를 사용할 수 있습니다.

2개의 xml 파일 생성 후.

  • messages.properties (xml 파일)
    • greeting=Hello, {0}
  • messages_ko_kr.properties (xml 파일)
    • greeting=안녕, {0}
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(messageSource.getClass());
        System.out.println(messageSource.getMessage("greeting", new String[]{"jaeuk"}, Locale.KOREA));
        System.out.println(messageSource.getMessage("greeting", new String[]{"jaeuk"}, Locale.getDefault()));
    }
}

Locale.KOREA 설정으로 messages_ko_kr.properties가 읽힌 것을 알 수 있고,
제 환경에서는 동일하게 나왔지만, 실습 강사님한테는 영어로 출력된 것을 확인했습니다.

class org.springframework.context.support.ResourceBundleMessageSource
안녕, jaeuk
Hello, jaeuk

동작 원리

  • MessageSource 구현체
    • org.springframework.context.support.ResourceBundleMessageSource

      ResourceBundle 클래스와 MessageFormat클래스 기반으로 만들어 졌으며, 번들에 특정 이름으로 접근가능.

    • org.springframework.context.support.ReloadableResourceBundleMessageSource

      프로퍼티 설정으로 reloading 하여 application 실행 와중에 번들 변경이 가능하다.

    • org.springframework.context.support.StaticMessageSource

      MessageSource의 가장 간단한 구현체로 기본적인 국제화를 지원하면 테스트 용도로 만들어짐.

참고

Spring에서 지원하는 MessageSource 3가지 구현체이다.
위의 Class에 대한 bean을 정의하면 ApplicationContext접근을 통하여 대상 메시지를 출력할 수 있다.
이 중 ReloadableResourceBundleMessageSource는 메시지 내용을 캐시하여 가지고 있으며, 인터벌을 지정하여 초단위 간격으로 메시지 파일을 재로딩 하여 어플리케이션의 종료 없이 properties 파일 수정으로 메시지 값 변경이 가능하다.

ResourceBundleMessageSource 빈이 messagese 라는 리소스 번들을 읽게 되어 있다.

스프링 부트에서 자동으로 해 주지만, 우리가 직접 설정을 할 수도 있다.

@SpringBootApplication
@PropertySource("classpath:/app.properties")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

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

다음은 ReloadableResourceBundleMessageSource를 활용해서,
어플리케이션의 종료 없이 properties 파일 수정으로 메시지 값 변경하는 예제를 구현해보자.

1초마다 찍으면서 리소스를 캐시하는 시간을 3초까지만 캐싱을 하고 다시 읽도록 세팅.
즉, 1초마다 메세지가 찍히고, 수정사항이 3초마다 반영된다. (캐싱은 3초, 값 변경 후 3초면 반영)

@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        while(true){
            System.out.println(messageSource.getClass());
            System.out.println(messageSource.getMessage("greeting", new String[]{"jaeuk"}, Locale.KOREA));
            System.out.println(messageSource.getMessage("greeting", new String[]{"jaeuk"}, Locale.getDefault()));
            Thread.sleep(1000l);
        }
    }
}
@SpringBootApplication
@PropertySource("classpath:/app.properties")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

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

이렇게 구현된 상태에서 프로퍼티 메세지를 변경하고 빌드만 하면 변경된 메세지가 바로 적용되어서 보여진다.




© 2019. by jaeuk