[MVC2] 3. 메시지, 국제화

kiwonkim·2021년 10월 21일
0

메시지 기능의 필요성

"상품명" 이라는 단어를 모두 "상품 이름"으로 변경해야 한다고 가정하자. 하드코딩으로 할 경우 프로젝트 내에 수백개의 단어를 수정해야될 수도 있다. 이를 방지하기 위해 Key:Value로 메시지를 저장하고, 수정시 일괄적으로 수정할 수 있게 하는 메시지 기능이 존재한다. 또한 국가마다 해당 메시지를 다르게 출력하는 국제화 기능도 있다.



스프링 부트의 메시지 소스

spring.messages.basename=messages
  1. 스프링부트는 메시지를 가져오는데 사용할 MessageSource 객체를 자동으로 빈으로 등록한다.
  2. application.properties 에서 메시지를 가져올 번들 이름을 지정한다. 디폴트는 messages로 되어있다.
  3. 번들 이름에 해당하는 properties 파일들을 생성한다. key 와 value 형태로 지정한다.
  4. 메시지가 필요한 곳에 MessageSource 객체를 주입하고. getMessage 로 메시지를 가져온다.


Properties 파일

--- message.properties ---
hello=안녕
hello.name=안녕 {0}

--- messages_en.properties ---
hello=hello
hello.name=hello {0}

메시지는 key=value 형태로 저장하며. {0} 을 이용해 파라미터를 추가할 수도 있다.
번들이름.properties는 디폴트 properties 파일이며. _en, _kr 등을 통해 국가별 properties 파일을 생성할 수 있다.



사용 예시

    // getMessage 함수 호출.
    @Test
    void helloMessage() {
        String result = ms.getMessage("hello", null, null); //key 정보. arg 정보. local 정보.
        assertThat(result).isEqualTo("안녕");
    }
    
    // 해당 메시지 존재하지 않을 경우 NoSuchMessageException 터짐
    @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("기본 메시지");
    }

    // 파라미터가 있는 메시지의 경우 getMessage의 두번째 파라미터로 Object 배열 넘겨서 채워줌.
    @Test
    void argumentMessage() {
        String message = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
        assertThat(message).isEqualTo("안녕 Spring");
    }
	
    // 존재하지 않는 Local 사용시 디폴트 로케일 사용하게됨.
    @Test
    void defaultLang() {
        assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
        assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕"); 
    }
    
    // 로케일이 ENGLISH 이므로 en이 붙은 properties에서 메시지를 가져옴. 
    @Test
    void enLang() {
        assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
    }


타임리프에서 사용

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

<div th:text="#{hello.name{${item.itemName}}">
  
<div>안녕 지우개

item.itemName이 지우개라 가정하자. 위처럼 사용시 아래로 렌더링 된다.



스프링의 Locale 선택

타임리프에서도 결국 getMessage를 사용하여 메시지를 렌더링하는 것이다. 이때 세번째 파라미터로 로케일이 들어가므로 스프링에서 로케일을 바탕으로 선택해줘야한다.

ms.getMessage("hello", null, Locale.ENGLISH)

스프링은 Locale 선택 방식을 다른것으로 변경할 수 있도록 LocaleResolver 인터페이스를 제공하는데 기본적인 구현체는 Http 요청의 Accept-Language 헤더의 값을 바탕으로 로케일을 선택하는 AcceptHeaderLocaleResolver로 되어있다. 구현체를 변경하는 방식으로 Locale 선택방식을 변경할 수 있다.



본 글은 김영한님의 "스프링 MVC 2편 - 백엔드 웹 개발 활용 기술" 강의내용 및 이해한 내용을 정리한 것입니다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard

0개의 댓글