3 분 소요

 인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술편을 학습하고 정리한 내용 입니다.

스프링 메시지 소스 설정

스프링은 기본적인 메시지 관리 기능을 제공한다.

메시지 관리 기능을 사용하려면 스프링이 제공하는 MessageSource를 스프링 빈으로 등록하면 되는데,

MessageSource는 인터페이스이다.

따라서 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하면 된다. (부트는 알아서 해준다.)

1
2
3
4
5
6
7
8
@Bean  
public MessageSource messageSource() {  
    ResourceBundleMessageSource messageSource = new  
          ResourceBundleMessageSource();  
    messageSource.setBasenames("messages", "errors");  
    messageSource.setDefaultEncoding("utf-8");  
    return messageSource;  
}
  • basenames : 설정 파일의 이름을 지정한다.
    • messages로 지정하면 messages.properties파일을 읽어서 사용한다.
    • 추가로 국제화 기능을 적용하려면 messages_en.properties, messages_ko.properties와 같이 파일 명 마지막에 언어 정보를 주면 된다. 만약 찾을 수 있는 국제화 파일이 없으면 messages.properties(언어 정보가 없는 파일 명)를 기본으로 사용한다.
    • 파일의 위치는 /resources/messages.properties에 두면 된다.
    • 여러 파일을 한번에 지정할 수 있다. 여기서는 messages, errors둘을 지정했다.
  • defaultEncoding : 인코딩 정보를 지정한다. `utf-8 을 사용하면 된다

스프링 부트 메시지 소스 설정

스프링 부트를 사용하면 다음과 같이 메시지 소스를 설정 할 수 있다.

application.properties

1
spring.messages.basename=messages,config.i18n.messages

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

1
spring.messages.basename=messages

MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages라는 이름으로 기본 등록 된다.

따라서 messages_en.properties, messages_ko.properties, messages.properties파일만 등록하면 자동으로 인식한다.

메시지 파일 만들기

이제 파일을 만들어 보자. 국제화 테스트를 위해 messages_en파일도 추가하자.

  • messages.properties : 기본 값으로 사용 (한글)
  • messages_en.properties : 영어 국제화 사용

/resources/messages.properties

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

/resources/messages_en.properties

1
2
hello=hello  
hello.name=hello {0}

다음과 같이 만들면 인텔리제이가 이렇게 모아서 보여주긴 한다. 폴더는 /resources/ 이다.

스프링 메시지 소스 사용

MessageSource 인터페이스

1
2
3
4
5
6
7
8
public interface MessageSource {  
    @Nullable  
    String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);  
  
    String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;  
  
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;  
}

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

스프링이 제공하는 메시지 소스를 어떻게 사용하는지 테스트 코드를 통해 알아보자.

테스트 - 사용해 보기기

test/java/hello/itemservice/message/MessageSourceTest.java

1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootTest  
public class MessageSourceTest {  
  
    @Autowired  
    MessageSource ms;  
  
    @Test  
    void helloMessage() {  
        String result = ms.getMessage("hello", null, null);  
        assertThat(result).isEqualTo("안녕");  
    }  
}

테스트 결과에서 result??로 나온다면

인텔리제이 Settings - Editor - File Encodings - Default encoding for properties files 옵션 utf-8 로 바꿔보자.

  • ms.getMessage("hello", null, null)
    • code : hello
    • args : null
    • locale : null

가장 단순한 테스트는 메시지 코드로 hello를 입력하고 나머지 값은 null을 입력했다.

locale정보가 없으면 basename에서 설정한 기본 이름 메시지 파일을 조회한다. basename 으로 messages를 지정했으므로 messages.properties파일에서 데이터 조회한다.

MessageSourceTest 추가 - 메시지가 없는 경우, 기본 메시지

1
2
3
4
5
6
7
8
9
10
11
12
@Test  
void notFoundMessageCode() {  
    assertThatThrownBy(() -> ms.getMessage("no_code", null, null))  
            .isInstanceOf(NoSuchMessageException.class);   
}

@Test  
void notFoundMessageCodeDefaultMessage() {  
    String result = ms.getMessage("no_code", null, "기본 메시지",  null);  
  
    assertThat(result).isEqualTo("기본 메시지");  
}

  • 메시지가 없는 경우에는 NoSuchMessageException이 발생한다.
  • 메시지가 없어도 기본 메시지(defaultMessage)를 사용하면 기본 메시지가 반환 된다.

MessageSourceTest 추가 - 매개변수 사용

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

다음 메시지의 {0} 부분은 매개변수를 전달해서 치환할 수 있다.

hello.name=안녕 {0} → Spring 단어를 매개변수로 전달 → 안녕 Spring

국제화 파일 선택

locale정보를 기반으로 국제화 파일을 선택한다.

  • Locale이 en_US의 경우 messages_en_USmessages_enmessages 순서로 찾는다.
  • Locale에 맞추어 구체적인 것이 있으면 구체적인 것을 찾고, 없으면 디폴트를 찾는다고 이해하면 된다.

Locale정보가 없는 경우 Locale.getDefault()을 호출해서 시스템의 기본 로케일을 사용합니다.
예) locale = null 인 경우 시스템 기본 localeko_KR이므로 messages_ko.properties 조회 시도
조회 실패messages.properties조회

MessageSourceTest 추가 - 국제화 파일 선택 1

1
2
3
4
5
@Test  
void defaultLang() {  
    assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");  
    assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");  
}
  • ms.getMessage("hello", null, null) : locale정보가 없으므로 messages를 사용
  • ms.getMessage("hello", null, Locale.KOREA) : locale정보가 있지만, message_ko가 없으므로 messages를 사용

MessageSourceTest 추가 - 국제화 파일 선택 2

1
2
3
4
@Test  
void enLang() throws Exception {  
    assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");  
}
  • ms.getMessage("hello", null, Locale.ENGLISH) : locale 정보가 Locale.ENGLISH이므로 messages_en을 찾아서 사용

댓글남기기