[스프링 IoC 컨테이너와 빈]_08 MessageSource

1 minute read

MessageSource

국제화 (i18n) 기능을 제공하는 인터페이스.

ApplicationContext extends MessageSource
● getMessage(String code, Object[] args, String, default, Locale, loc)
● …

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

릴로딩 기능이 있는 메시지 소스 사용하기

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

MessageSource

  • 메시지를 다국화하는 방법

  • ApplicationContext가 MessageSource를 상속받았기 때문에 이 기능을 할 수 있다.

MessageSource 사용하기

※ [실습]

1. MessageSource에 해당하는 값을 별도의 파일로 생성

messages.properties, messages_ko_KR.properties, messages_en.properties

  • messages.properties
   greeting=Hello {0}
  • messages_ko_KR.properties
   greeting=안녕, {0}
  • messages_en.properties
   greeting=Hello, {0}

별도의 설정을 하지 않고, 위와같이 파일을 만들면 스프링부트 애플리케이션은 messages로 시작하는 MessageSource들을 전부 읽어주기 때문에 바로 사용할 수 있다.

자동으로 Bundle로 인식한다.

messages번들

2. ApplicationRunner에서 MessageSource 사용

   @Component
   public class AppRunner implements ApplicationRunner {
   
       @Autowired
       MessageSource messageSource;
   
       @Override
       public void run(ApplicationArguments args) throws Exception {
           System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.getDefault()));
           System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.KOREA));
           System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.ENGLISH));
       }
   }

다국화

(왜 default로 한글이 나오는지는 모르겠다.?)

원래는 관련빈을 빈으로 등록해줘야하는데, 스프링부트를 사용하면 미리 ResourceBundleMessageSource가 빈으로 등록되어있다. 이 빈이 messages라는 Resource Bundle을 읽게된다.

 System.out.println(messageSource.getClass()); //-> class org.springframework.context.support.ResourceBundleMessageSource

릴로딩 기능이 있는 메시지 소스 사용하기

스프링부트가 기본적으로 설정해주는 기능을 우리가 커스텀해서 사용할 수 있다.

※ [실습]

MessageSource를 직접 빈으로 등록

  • 빈 id는 항상 messageSource가 되어야한다.

  • setBasename

    • 메세지 프로퍼티파일의 위치와 이름을 지정
    • basename은 classpath 기준으로 줘야한다. messages를 읽는다.
  • setDefaultEncoding

    • 기본 인코딩을 지정
    • setDefaultEncoding(“UTF-8”) : 한글 인코딩
  • setCacheSeconds

    • 프로퍼티 파일의 변경을 감지할 시간 간격을 지정
  • setUseCodeAsDefaultMessage

    • 없는 메세지일 경우 예외를 발생시키는 대신 코드를 기본 메세지로 한다.

애플리케이션 실행 중에 프로퍼티 값을 변경 후, 재 빌드!!하면 값이 바로 적용된다.

@SpringBootApplication
public class Demospring51Application {

    public static void main(String[] args) {
        SpringApplication.run(Demospring51Application.class, args);
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:/messages");
        messageSource.setDefaultEncoding("UTF-8");
        messageSource.setCacheSeconds(3); //<-- 3초 마다 변경 감지
        return messageSource;
    }
}
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    MessageSource messageSource;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        while(true) {
            System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.getDefault()));
            System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.KOREA));
            System.out.println(messageSource.getMessage("greeting", new String[]{"Solar"}, Locale.ENGLISH));
            Thread.sleep(10001); //1초마다 콘솔에 찍으면서 값이 변경되는지 확인
        }
    }
}

참고

MessageSource messageSource; 대신 ApplicationContext messageSource 타입으로 받아서 사용할 수 있지만, 내가 사용하려는 인터페이스로 정확히 명시해주는 것이 어떤 의도로 사용하려는지 목적이 분명하므로 권장된다.