[Spring] 스프링 메시지, 국제화 기능으로 다국어 적용하기
메시지(Message) 기능
실무를 진행하다 보면 무언가의 이름이 바뀌는 건 심심치 않게 발생한다.
예를 들어 아주 사소하지만 "상품명"이라는 단어를 "상품이름"으로 바꾸라는 지시가 내려왔다고 하자.
만약 화면 수가 수십개가 넘어가는데 일일이 모든 단어를 수정하는 것은 귀찮고 비효율적일 것이다.
스프링은 이러한 다양한 메시지를 한 곳에서 관리할수 있는 메시지(Message) 기능을 제공한다.
예를 들어 아래와 같이 messages.properties 라는 메시지 관리 파일을 만들어 관리할 수 있다.
item.itemName=상품명
item.price=가격
item.quantity=수량
...
이렇게 메시지를 관리하면 상품명을 화면에서 사용할 때 "상품명"으로 하드코딩하지 않고 "item.itemName"으로 설정해 놓을 수 있다.
추후 "item.itemName=상품이름"으로 한 줄만 바꾸면 수많은 화면의 "item.itemName"을 한 번에 바꿀수 있는 것이다.
국제화
국제화는 메시지 관리 파일을 나라별로 만들어 관리하면 가능하다.
아래와 같이 한국 전용 메시지 관리 파일은 messages_ko.properties 로 관리하고
item.itemName=상품명
item.price=가격
item.quantity=수량
영어 전용은 messages_en.properties로 관리하는 것이다.
item.itemName=Item Name
item.price=price
item.quantity=quantity
...
이때 사이트에 접속한 사람이 한국어를 사용하는지, 영어를 사용하는지는 HTTP 요청의 헤더 값 중 accept-language 값을 참고하거나 사용자가 선택할 수 있도록 하면 된다.
스프링 메시지 소스 설정
스프링에서는 MessageSource를 스프링 빈으로 등록하면 메시지 관리 기능을 사용할 수 있다.
다만 MessageSource가 인터페이스이기 때문에 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하면 된다.
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages", "errors");
messageSource.setDefaultEncoding("utf-8");
return messageSource;
}
위에서 basenames로 지정한 messages.properties와 errors.properties 파일을 읽어 사용하게 된다.
여기에 message_en.properties와 같이 파일명 마지막에 언어 정보를 추가하면 국제화 기능을 사용할 수 있다.
메시지 관리 파일은 /resources 아래에 두면 된다.
스프링 부트 메시지 소스 설정
스프링 부트를 사용하면 MessageSource를 스프링 빈으로 자동 등록해 준다.
따라서 application.properties에서 아래와 같이 메시지 소스를 설정할 수 있다.
spring.messages.basename=messages
MessageSource를 스프링 빈으로 등록하지 않고 스프링 부트와 관련된 별도의 설정을 하지 않으면 basename이 messages로 기본 등록된다.
따라서 messeges_en.properties 등의 파일을 등록하면 자동으로 인식해 국제화 기능도 활용 가능하다.
활용
/resources/messages.properties
item.itemName=상품명
item.price=가격 {0}
item.quantity=수량
/resources/messages_en.properties
item.itemName=Item Name
item.price=price {0}
item.quantity=quantity
위와 같이 두 개의 메시지 관리 파일을 만들었다고 하자.
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void itemTest() {
// getMessage(code, args, locale)
String result = ms.getMessage("item.itemName", null, null);
assertThat(result).isEqualTo("상품명"); // true
}
}
MessageSource의 getMessage 메서드는 메시지 코드인 code, 매개변수인 args, 언어 정보인 locale을 파라미터로 받는다.
만약 locale 정보가 없으면 기본 messages.properties를 참조한다.
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void itemTest() {
String result = ms.getMessage("item.price", new Object[]{"원"}, null);
assertThat(result).isEqualTo("가격 원"); // true
}
}
item.price=가격 {0}와 같이 메시지의 {0} 부분은 매개변수를 전달해서 치환할 수 있다.
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void itemTest() {
String result = ms.getMessage("item.ItemName", null, Locale.ENGLISH);
assertThat(result).isEqualTo("Item Name"); // true
}
}
locale 정보로 Locale.ENGLISH를 전달했으므로 messages_en.properties를 참조한다.
이렇게 국제화 기능을 사용할 수 있다.
웹 애플리케이션 적용
타임리프를 사용한다면 타임리프의 메시지 표현식인 #{...}을 사용해 스프링의 메시지를 조회할 수 있다.
예를 들어
<h1 th:text="#{item.itemName}"></h1>
위와 같이 사용할 수 있다.
참고
[1] 인프런 김영한 강의 - https://www.inflearn.com/course/lecture?courseSlug=%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2&unitId=83388&tab=curriculum