그렇다면, 모든 html 파일의 “상품명” 을 모두 찾아서 모두 수정해야 한다. 매우 번거롭고 힘들고 실수가 발생할 수 있다. → 메시지
왜? 지금은 하드코딩 되어 있기 때문이다.
또는, 기본 locale 설정이 en 인 유저가 사이트에 접근하면, 영어로. ko 인 유저가 사이트에 접근하면, 한글로 랜더링 해주고 싶을 때 어떻게 해야 하나? → 국제화
message.properties 라는 메시지 관리용 파일을 만들고, 각 html은 파일의 데이터를 key 값으로 불러 사용하는 방식을 사용할 수 있다!
위의 두 문제는 “메시지” 와 “국제화” 로 해결할 수 있고, 이를 스프링이 어떻게 지원하는지 코드를 통해 알아보자.
스프링은 메시지 관리 기능을 기본으로 제공한다.
메시지 관리 기능을 사용하려면, 스프링이 제공하는 MessageSource 를 스프링 빈으로 등록해야 한다.
이때, 스프링 부트를 사용하면, 스프링 부트가 자동으로 MessageSource를 스프링 빈으로 등록한다.
만약, 직접 Spring Bean에 등록하고자 한다면?
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages", "errors");
messageSource.setDefaultEncoding("utf-8");
return messageSource;
}
만약, 직접 application.properties 에 등록하고 싶다면?
application.properties
spring.messages.basename=messages,config.i18n.messages
스프링 부트와 관련된 별도의 설정을 하지 않으면 messages 라 는 이름으로 기본 등록된다. 따라서 messages_en.properties , messages_ko.properties , messages.properties 파일만 등록하면 자동으로 인식된다.
국제화 테스트를 위해서 messages_en 파일을 추가한다.
결과적으로 메시지 source 라는 것이 스프링 빈에 등록되기 때문에, 이거를 가져다가 쓰기만 하면 된다.
MessageSource interface
public interface MessageSource {
String getMessage(String code, @Nullable Object[] args, @Nullable String
defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale)
throws NoSuchMessageException;
}
해당 인터페이스를 사용하는데, 이를 보면 일부 파라미터로 메시지를 읽어오는 기능을 제공한다.
messages.properties
hello=안녕
hello.name=안녕 {0}
messages_en.properties
hello=hello
hello.name=hello {0}
Test 를 통해 알아본다.
MessageSourceTest
메시징 테스트
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource messageSource;
@Test
void helloMessage() {
String result = messageSource.getMessage("hello", null, Locale.KOREA);
assertThat(result).isEqualTo("안녕");
}
@Test
void notFoundMessageCode() {
assertThatThrownBy(() -> messageSource.getMessage("no_code", null, null))
.isInstanceOf(NoSuchMessageException.class);
}
@Test
void notFoundMessageCodeDefaultMessage() {
String result = messageSource.getMessage("no_code", null, "기본 메시지", null);
assertThat(result).isEqualTo("기본 메시지");
}
@Test
void argumentMessage() {
String message = messageSource.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(message).isEqualTo("안녕 Spring");
}
}
국제화 테스트
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource messageSource;
@Test
void defalutLang() {
assertThat(messageSource.getMessage("hello", null, null)).isEqualTo("안녕");
assertThat(messageSource.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
@Test
void enLang() {
assertThat(messageSource.getMessage("hello", null, Locale.US)).isEqualTo("hello");
assertThat(messageSource.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
}
}
messages.properties 추가
label.item=상품
label.item.id=상품 ID
label.item.itemName=상품명
label.item.price=가격
label.item.quantity=수량
page.items=상품 목록
page.item=상품 상세
page.addItem=상품 등록
page.updateItem=상품 수정
button.save=저장
button.cancel=취소
messages_en.properties 추가
label.item=Item
label.item.id=Item ID
label.item.itemName=Item Name
label.item.price=price
label.item.quantity=quantity
page.items=Item List
page.item=Item Detail
page.addItem=Item Add
page.updateItem=Item Update
button.save=Save
button.cancel=Cancel
타임리프 메시지 표현식 “#{ … }" 를 사용하면, 스프링 빈에 등록된 메시지를 조회하여 사용할 수 있다.
예) 상품 이라는 이름을 조회하려면, “#{label.item}" 을 사용하면 된다.
Before : addForm.html
<h2>상품 등록 폼</h2>
After : addForm.html
<h2 th:text = "#{page.addItem}"></h2>
동일한 방법으로 나머지 항목도 수정해 준다.
만약, 파라미터를 사용하고 싶다면?
messages.properties 추가
testLabel = 상품 {0}
testList = 목록
items.html 적용
<h2 th:text="#{testLabel(#{testList})}">상품 목록 default value</h2>
messages_en.properties 에 적용한 것들을 영어로 랜더링해서 보여주자.
그러기 위해서 messages.properties 와 동일한 이름으로 값들을 만들어주면 된다.
웹 브라우저에서 설정 → 언어 → 영어를 맨 위로 하고 새로고침 해보자.
실행 결과

