스프링 프레임워크 MessageSource 설정

백기선님의 ‘스프링 프레임워크 핵심 기술’ 강의 정리

MessageSource

  • 국제화(i18n) 기능을 제공하는 인터페이스
public interface ApplicationContext extends MessageSource ... {
    
    String getMessage(String code, @Nullable Object[] args, Locale locale)
}
  • ApplicationContextMessageSource를 상속받으므로 ApplicationContext를 주입받으면, MessageSource 기능도 사용 가능

  • 스프링 부트를 사용하면 설정없이 messages.properties 사용 가능

    • messages_ko_KR.properties

    • message_en_US.properties

메세지 프로퍼티를 추가해서 앱 러너에서 확인해보도록 하자.

# messages_ko_KR.properties
greeting=안녕 {0}

# messages.properties
greeting=Hello {0}

앱 러너에서도 메세지를 가져올 수 있도록 코드를 추가한다.

@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[]{"there"}, Locale.getDefault()));
		System.out.println(messageSource.getMessage("greeting", new String[]{"there"}, Locale.KOREA));

	}
}

앱을 실행하자 ?? there 이라는 문구만 출력됐다. 인코딩 문제를 먼저 해결해야만 했다. 인텔리제이에서 Preferences - Editor - Code Style - File Encodings 에서 UTF-8 설정을 해줘야만 한다. 그냥 Preferences에서 encoding만 검색해도 빠르게 찾을 수 있다. 아래의 표시된 곳의 인코딩 설정을 UTF-8로 바꿔주도록 한다. 인젤리제이 인코딩 설정

인코딩 설정을 마치고 다시 앱을 실행하자 안녕 there이 두 번 출력되었다. Locale 기본값이 한국어로 되어있던 듯 했다. 영어 버전을 출력하기 위해 프로퍼티를 여러번 수정해보았다. 기본 locale이 한국어이기 때문에 기존의 messages_ko_KR.propertiesmessages.properties로 바꾸고 영어 버전을 추가하기 위해 message_en_US.properties로 변경했다. 앱 러너에서는 Locale.ENGLISH 로 설정하도록 했다.

# messages.properties
greeting=안녕 {0}

# messages_en_US.properties
greeting=Hello {0}
@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[]{"there"}, Locale.getDefault()));
		System.out.println(messageSource.getMessage("greeting", new String[]{"there"}, Locale.ENGLISH));

	}
}

이렇게 설정하고 앱을 실행하자 Locale.getDefault()로 설정한 곳은 한국어로, Locale.ENGLISH로 설정한 곳은 영어 설정을 읽어서 의도대로 잘 출력되었다.

MessageSource를 빈으로 등록해서 원하는대로 설정을 할수도 있다. UTF-8 설정을 해주지 않으면 인코딩이 깨지므로 여기에도 인코딩 설정을 해주도록 한다.

@SpringBootApplication
public class SpringCoreApplication {

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

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

}

그 다음, 앱 러너로 가서 기존의 문구를 1초 간격으로 출력하도록 코드를 조금 수정해본다.

@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[]{"there"}, Locale.getDefault()));
			System.out.println(messageSource.getMessage("greeting", new String[]{"there"}, Locale.ENGLISH));
			Thread.sleep(1000L);
		}
	}
}

리로드가 가능한 메세지소스를 빈으로 등록했기 때문에 중간에 메세지 프로퍼티를 수정해도 바로 반영이 된다. 메세지 소스의 캐시 시간 설정만 추가해주도록 한다.

@SpringBootApplication
public class SpringCoreApplication {

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

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

}

이렇게 모두 수정한 후에 앱을 실행하면 계속 문구가 출력될 것이다. 중간에 메세지 프로퍼티의 문구를 바꿔준 후에 Build - Build Project를 클릭하면 앱을 껐다가 다시 실행하지 않아도 바꾼 메세지가 적용된다. 빌드된 디렉토리의 클래스패스를 읽어들여서 동작하기 때문에 꼭 프로젝트 빌드를 해줘야 한다.