Message, internationalization

메시지와 국제화란?

  • 메시지
    • 공통적으로 사용되는 문구에 대해서 미리 설정을 해두는 것
    • ex) ‘상품 이름’ 이라는 label에 붙은 문구를 전체적으로 ‘상품 명’ 으로 변경하고 싶은 상황 → 메시지 기능을 사용하지 않는다면, 직접 일일이 다 수정해주어야 됨 (수정해야 될 html 파일이 200개가 있다고 생각해보면 끔찍..!) → 메시지 기능을 사용하면, message 설정 부분 하나만 수정해주면 공통적으로 적용 됨!
  • 국제화
    • 메시지에서 한 발 더 나아간 개념
    • 요청하는 고객이 선택한 언어에 맞는 메시지를 보여주는 것!
    • 한국, 영어 에 대한 메시지 국제화 설정이 되어 있으면, 한국에서 요청한 것이면 한국어로, 영어권에서 요청한 것이라면 영어로 각 문구들을 보여주는 것
    • 접근 국가 인식 방법
      • HTTP 헤더들 중 accept-language 헤더 값 이용
      • 사용자가 직접 선택한 언어를 쿠키에 녹여 처리
  • 이런 메시지와 국제화 기능은 직접 구현 가능. BUT, Spring은 기본적인 메시지와 국제화 기능 모두 제공! (Thymeleaf 또한 제공 → Thymelaef, Spring Integration)
  • 즉, 스프링에서 정해준 메시지 규약을 따르면 편리하게 메시지, 국제화 기능을 사용할 수 있음

메시지, 국제화 in Spring

스프링 메시지 소스 설정

  • Spring Boot를 사용하지 않을 때 (Only Spring)

      @Bean
      public MessageSource messageSource() {
      	 ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      	 messageSource.setBasenames("messages", "errors");
      	 messageSource.setDefaultEncoding("utf-8");
      	 return messageSource;
      }
    
    • MessageSource스프링 빈으로 등록
    • MessageSource 는 Interface 이기에 구현체인 ResourceBundleMessageSource 를 스프링 Bean 으로 등록
    • setBasenames : 메시지 설정 파일의 이름 지정
      • messages로 지정하면 messages.properties 파일을 읽어서 사용
      • 국제화 설정 : _en, _ko 처럼 뒤에 언어 정보를 넣어 주어 생성해주면 됨(messages_en.properties, …) 지정되어 있지 않은 언어에 대해선 default인 messages.properties 이용
      • 메시지 설정 파일의 위치/resources 하위에 두면 됨
      • 여러 파일 한번에 지정 가능 (messages, errors, …)
    • setDefaultEncoding : 인코딩 정보 지정
  • Spring Boot에서의 메시지 소스 설정
    • 자동으로 MessageSource스프링 빈으로 등록 (Spring Boot를 쓰는 이유 중 하나)
    • 추가적인 basename, encoding 정보application.properties 에 설정해주면 됨
    • 하지만 이것 또한 default로 basename = message, encoding=utf-8 로 되어 있음!!
    • 만약 추가적인 메시지 파일을 사용하려면 해당 설정에 추가해주면 됨 → spring.messages.basename=messages,errors
    • 국제화 기능은 동일하게 메시지 파일 뒤에 _en, _ko 처럼 언어 정보를 넣어 주어 생성해주면 됨
  • 메시지 파일 예시
    • /resources/messages.properties

        hello=안녕
        hello.name=안녕 {0}
      
      • {0}파라미터를 넣는 공간
      • 즉, message는 파라미터도 지원
    • /resources/messages_en.properties

        hello=hello
        hello.name=hello {0}
      
      • 영어로 요청이 들어오면 해당 파일의 메시지가 적용 되는 것

스프링 메시지 소스 사용

  • MessageSource Interface 메서드 살펴보기
    • String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
      • String code : message code (messages.properties에 등록되어 있는 code)
      • Object[] args : message code가 파라미터를 요구할 때 넣어주는 파라미터 값들
      • String defaultMessage : 해당 되는 message code가 없을 때 대신해서 보여주는 ‘기본 메시지
      • Locale locale : 지역 정보 (_en, _ko, …) 등에 맞는 언어 메시지 선택을 위함.
    • String getMessage(String code, @Nullable Object[] args, Locale locale);
      • defaultMessage를 잘 사용하지 않기에 defaultMessage 제외된 method
  • MessageSource 사용 (위의 messages.properties 를 바탕으로)
    • messages.properties 에서 message 불러오기 (args : null, locale : null) ms.getMessage("hello", null, null); → “안녕”
    • messages.properties 에 없는 message 불러오기(No deafultMessage) -> 예외 발생 ms.getMessage("no_code", null, null))NoSuchMessageException 발생
    • messages.properties 에 없는 message 불러오기(기본 메시지로 출력하기) ms.getMessage("no_code", null,"기본 메시지", null); → “기본 메시지”
    • message args 와 함께 사용하기 ms.getMessage("hello.name", new Object[]{"Spring"}, null); → “안녕 Spring” ( hello.name = 안녕 {0})
    • locale에 따른 message 불러오기
      • ms.getMessage("hello", null, Locale.*KOREA*) → “안녕” (_ko 로 설정된 메시지 파일이 없기에 기본 messages.properties에서 가져온 것)
      • ms.getMessage("hello", null, Locale.*ENGLISH →* “hello” (_en 의 메시지 파일이 있기에 messages_en.properties에서 가져온 것)

웹 애플리케이션에 메시지, 국제화 적용

  • Thymeleaf(View Template)는 Spring과 통합되어 메시지, 국제화 기능을 제공함.
  • 즉, 별다른 설정없이 Thymeleaf의 메시지 사용 규율만 따르면 편리하게 사용 가능
  • Thymeleaf에서 메시지 사용하기
    • th:text="#{...}"
      • messages.properties
        label.item=상품
        label.item.name=상품명
        label.item.price=상품가격
        label.item.param=상품 {0}
      
      • 메시지 사용 전 : <h2> 상품명 </h2>
      • 메시지 사용 후 : <h2 th:text="#{label.item.name}"> 상품명 </h2> → 렌더링 → <h2> 상품명 </h2>
        • messages.properites에서 label.item.name 이라는 message를 가져와 text content로 사용하는 것!
      • 이렇게 되면 만약 “상품명” 이라는 text를 전체적으로 “상품 이름” 으로 변경하고 싶으면 그냥 messages.propertes에서 label.item.name 부분만 수정해주면 됨!! → 유지 보수 효율 UP
      • 파라미터 사용
        • "#{...(...)}"
        • <p th:text="#{label.item.param(${item.param})}"></p>
  • Thymeleaf에서 국제화 사용하기
    • 사용법은 메시지와 동일!
    • messages_en.properties를 설정해 두었다면 Thymeleaf가 알아서 자동으로 Accept-Language 헤더의 locale 정보를 통해 국제화를 실행시켜 줌! (LocaleResolver interface의 구현체인 AcceptHeaderLocaleResolver 를 통해)
    • Ex)
      • messages_en.properties
        label.item=item
        label.item.name=item name
        label.item.price=item price
        label.item.param=item {0}
      
      • Accept-Language : ko,en;q=0.9,…
        • Local : _ko
        • 하지만 messages_ko.properties가 따로 없기에 default messages인 messages.properties 사용
        • <h2 th:text="#{label.item.name}"> 상품명 </h2> → 렌더링 → <h2> 상품명 </h2>
      • Accept-Language : en,ko;q=0.9,…
        • Local : _en
        • messages_en.properties가 있기에 해당 메시지 정보를 이용
        • <h2 th:text="#{label.item.name}"> 상품명 </h2> → 렌더링 → <h2> item name </h2>