JAVA/Spring

메시지, 국제화

sihyeong 2023. 12. 4. 16:10

메시지

만약 화면에 보이는 문구인 상품명이라는 단어를 모두 상품이름으로 변경하고자 한다면 어떻게 해야 할까? 상품명이 적힌 화면들을 다 찾아가면서 모두 변경해야 한다. 만약 해당 화면이 수십, 수백개라면 어떨까?

 

이러한 다양한 메시지를 한 곳에서 관리하도록 하는 기능을 메시지 기능이라 한다.

 

예를들어 messages.properties 라는 메시지 관리용 파일을 만들고

item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

 

각 HTML들은 다음과 같이 해당 데이터를 key 값으로 불러서 사용하는 것이다.

<label for="itemName" th:text="#{item.itemName}"></label>

국제화

메시지에서 한반 더 나아가면, 메시지에서 설명한 메시지파일(messages.properties)를 각 나라별로 별도로 관리하면 서비스를 국제화 할 수 있다.

 

다음과 같이 영어, 한국 버전의 파일을 만들어 분류하면 된다.

 

messages_en.properties

item=Item
item.id=Item ID
item.itemName=Item Name
item.price=price
item.quantity=quantity

 

messages_ko.properties

item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량

 

영어를 사용하는 사람이 웹에 접근한다면 messages_en.properties를 사용하고,

한국어를 사용하는 사람이면 messages_ko.properties를 사용하게 개발하면 

 

사이트를 국제화 할 수 있다.

 

한국에서 접근한 것인지, 영어에서 접근한 것인지 판단 근거HTTP 헤더accept-language 값을 토대로 판단하거나 사용자가 직접 언어를 선택하도록 하고, 쿠키 등을 사용해서 처리하면 된다.


스프링의 메시지 소스 설정

스프링의 메시지 관리 기능을 사용하려면 스프링이 제공하는 MessageSource 인터페이스를 스프링 빈으로 등록하면 동작하게 된다.

 

MessageSource는 인터페이스기 때문에 구현체ResourceBundleMessageSurce를 스프링 빈으로 등록하면 된다.

 

@Bean
public MessageSource messageSource(){
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("messages", "errors");
    messageSource.setDefaultEncoding("utf-8");
    return messageSource;
}

 

  • basenames: 등록할 .properties 파일의 이름을 지정한다.
    • messages로 지정하면 messages.properties 파일을 읽어 사용하게 된다.
    • 추가로 국제화 기능을 적용 시 messages_en.properties, messages_ko.properties와 같이 파일명 마지막에 언어 정보를 추가하면 국제화를 사용할 수 있다.
    • 만약 사용 국가에 맞는 국제화 파일이 없다면 messages.properties(언어정보가 없는 파일명)기본으로 사용하게 된다.
    • .properties의 파일 위치는 /resources/messages.properties에 두면 된다.
    • 한번에 여러 파일을 지정할 수 있다. 이 예제에서는 messages와 errors 2개를 메시지파일로 지정했다.
  • defaultEncoding: 인코딩 정보를 지정한다. 보통 기본적으로 utf-8을 사용한다.

스프링 부트 메시지 소스 기본값

스프링 부트를 사용하면 부트가 MessageSource 자동으로 스프링 으로 등록하기 때문에 별도의 MessageSource 빈 등록 없이 사용할 수 있다.

 

application.properties를 통해 세부 정보를 수정할 수 있다.

별도의 메시지 소스 설정을 하지 않는다면

 

basename(등록할 properties 파일명)은 messages, 인코딩 정보는 utf-8로 기본 등록된다.

 

 

스프링 부트 application.properties의 메시지  기본값


메세지 소스 사용

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;

 

MessageSource 인터페이스를 보면 코드를 포함한 일부 파라미터로 메시지를 읽어오는 기능을 제공한다.

 

Messages.properties

hello=안녕
hello.name=안녕 {0}

Messages_en.properties

hello=hello
hello.name=hello {0}

 

 

@SpringBootTest
public class MessageSourceTest {

     @Autowired
     MessageSource ms;
     
     @Test
     void helloMessage() {
         String result = ms.getMessage("hello", null, null);
         assertThat(result).isEqualTo("안녕");
     }
}

 

application.properties의 메시지 설정 기본값인 basename=messages에 따라 messages.properties파일에서 "hello" 를 조회하여 출력한다.

 

메시지 소스 매개변수 사용

@Test
void argumentMessage() {
     String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
     assertThat(result).isEqualTo("안녕 Spring");
}

 

hello.name=안녕 {0} 의 {0} 부분에 new Object[]{"Spring"}이 매개변수로 전달되어 최종적으로 안녕 Spring이 출력된다.

 

국제화 파일 선택

@Test
void lang() {
     assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
     assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
     assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
}

 

ms.getMessage("hello", null, null): locale 정보가 없으므로 Locale.getDefault()를 호출해서 시스템의 기본 로케일을 사용한다. 만약 시스템에 맞는 파일이 없다면 기본값인 messages.properties를 조회한다.


타임리프 메시지 적용

타임리프의 메시지 표현식 #{...}를 사용하면 스프링의 메시지를 편리하게 조회할 수 있다.

위에서 등록한 hello를 조회하려면

<div th:text="#{hello}"></div>

 

와 같이 사용할 수 있다.

 

렌더링 후 :

<div>안녕</div>

 

이러한 방법으로 여러 메시지를 등록한 뒤 한번에 값을 수정하는 등의 동작으로 여러 값들을 관리할 수 있다.

 

타임리프 파라미터 사용법 : 

<p th:text="#{hello.name(${data})}"></p>

 

다음과 같이 #{...(파라미터값) }으로 동작한다.