[Spring] 메시지, 국제화

·2023년 11월 22일

Spring

목록 보기
1/26
post-thumbnail

💡메시지

  • 여러 화면에 보이는 상품명, 가격, 수량 등의 단어를 변경하려면 HTML파일에 하드코딩 되어 있는 여러개의 화면들을 다 찾아가면서 모두 변경해야한다

  • 이러한 문제점을 해결하기 위해 다양한 메시지를 한 곳에 관리하는 기능을 메시지 기능 이라고 한다.

📗예시

예를 들어 messages.properties라는 메시지 관리용 파일을 만들어서 아래와 같이 작성해준다.

item = 샹품
item.id = 상품 ID
item.itemName = 상품명
item.price = 가격
  • 각 HTML들은 해당 데이터를 KEY 값으로 불러 사용하게 된다.
    • <label for="itemName" th:text="#{item.itemName}"></label>

💡국제화

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

📗예시

messages_en.properties

item=Item
item.id=Item IDitem.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는 인터페이스 이므로 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록해야한다.

직접 등록

@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를 기본으로 사용한다.
  • defaultEncodeing : 인코딩 정보를 지정한다.

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

  • 스프링 부트를 사용하면 스프링 부트가 MessageSource를 자동으로 스프링 빈으로 등록한다.

aplication.properties

spring.messages.basename=messages
  • MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages라는 이름으로 기본 등록 된다.
  • 즉, messages_en.properties,messages_ko.properties, messages.properties파일만 등록하면 자동으로 인식된다.

메시지 파일 만들기

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

messages.properties

/resources/messages.properties

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

messages_en.properties

/resources/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);
        Assertions.assertThat(result).isEqualTo("안녕");
    }
 }
  • ms.getMessage("hello", null,null)
    • code : hello
    • agrs : null
    • locale : null
  • locale 정보가 없으면 basename에서 설정한 기본 이름 메시지 파일을 조회한다.
  • basename으로 messages를 지정했으므로 messages.properties파일에서 데이터를 조회한다.

메시지가 없는 경우 - 기본 메시지

 @Test
    void notFoundMessageCode(){
        assertThatThrownBy(() -> ms.getMessage("no_code", null, null))
                .isInstanceOf(NoSuchMessageException.class);
    }

    @Test
    void notFounrMessageCodeDefaultMessage(){
        String result = ms.getMessage("no_code",null,"기본 메시지", null);
        Assertions.assertThat(result).isEqualTo("기본 메시지");
    }
  • 메시지가 없는 경우, NoSuchMessageException예외가 발생한다.
  • 기본 메시지(defaultMessage)를 사용하면 메시지가 없어도 기본 메시지가 반환된다.

매개변수 사용

@Test
    void argumentMessage(){
        String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
        Assertions.assertThat(result).isEqualTo("안녕 Spring");
    }
  • properties파일의 {0}부분은 매개변수를 전달해서 치환할 수 있다.
    - hello.name=안녕 {0} -> 안녕 Spring

국제화 파일 선택

@Test
    void defaultLang(){
        Assertions.assertThat(ms.getMessage("hello",null,null)).isEqualTo("안녕");
        Assertions.assertThat(ms.getMessage("hello",null, Locale.KOREA)).isEqualTo("안녕");
    }
@Test
   void enLang(){
        Assertions.assertThat(ms.getMessage("hello",null,Locale.ENGLISH)).isEqualTo("hello");
    }
   
  • ms.getMessage("hello",null,null) : locale정보가 없으므로 messages.사용
  • ms.getMessage("hello",null, Locale.KOREA) : locale 정보가 있지만, message_ko가 없으므로 messages 사용
  • ms.getMessage("hello",null,Locale.ENGLISH) : locale정보가 Locale.ENGLISH이므로 messages_en를 찾아서 사용

💡웹 애플리케이션에 메시지 적용하기

  • 실제 웹 애플리케이션에 메시지를 적용해보자

messages.properties

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

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=취소
button.update=수정
button.add=등록

타임리프 메시지 적용

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

addForm.html

  • 타임리프의 메시지 표현식을 작성하고, 아무 의미 없는 값들을 하드코딩했다.
  • 메시지가 없다면 하드코딩한 아무의미 없는 숫자들이 나올 것이고, 메시지가 있다면 지정한 메시지 대로 나올 것이다.

출력 결과

- 메시지대로 잘 나오는 것을 확인할 수 있다.

💡웹 애플리케이션에 국제화 적용하기

  • 이미 html파일에서 #{...}을 통해 메시지를 적용하도록 작성했기 때문에 설정파일만 추가해주면 국제화가 가능하다.

    messages_en.properties

hello=hello
hello.name=hello {0}

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
button.update=Update
button.add=Add
profile
배우고 기록하며 성장하는 백엔드 개발자입니다!

0개의 댓글