리서치

[SpringBoot] yml 파일로 메세지 다국어 처리

꾸준함. 2024. 2. 14. 01:18

개요

진행 중인 프로젝트에 다국어 처리를 추가해야 하는데, 공식 문서에서 제시한 properties 파일 대신 yml 파일을 사용하고 싶었고, 조사 결과 이를 가능하게 하는 라이브러리가 존재했습니다.

https://github.com/akkinoc/yaml-resource-bundle?tab=readme-ov-file

 

GitHub - akkinoc/yaml-resource-bundle: Java ResourceBundle for YAML format.

Java ResourceBundle for YAML format. Contribute to akkinoc/yaml-resource-bundle development by creating an account on GitHub.

github.com

 

이 게시글에서는 스프링 부트 프로젝트에 해당 라이브러리를 어떻게 접목시킬지 간단히 설명하겠습니다.

 

프로젝트 환경

  • Springboot 2.6.3
  • Java 1.8
  • yaml-resource-bundle 2.8.1

 

다국어 처리를 위해 구현해야 할 Configuration  클래스

다국어 처리를 적용하기 위해서는 두 가지의 Configuration 클래스를 구현해야 합니다.

  • MessageConfiguration
  • LocaleConfiguration

 

1. MessageConfiguration

 

MessageSource는 국제화(i18n)를 제공하는 인터페이스이며 MessageConfiguration에서 yaml-resource-bundle에서 제공하는 커스텀 MessageSource인 YamlMessageSource를 빈으로 등록해야 합니다.

 

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import dev.akkinoc.util.YamlResourceBundle;
/**
* 참고: https://github.com/ttasjwi/trilo-be/blob/258463cdf208cfd28d47af242e2695dd5ef5db42/src/main/resources/exceptions/exception_en.yml
*/
@Configuration
public class MessageConfiguration {
@Bean
public MessageSource messageSource() {
YamlMessageSource messageSource = new YamlMessageSource();
messageSource.setBasename("resource"); // 메시지를 찾을 위치
messageSource.setDefaultEncoding("UTF-8"); // 인코딩
messageSource.setAlwaysUseMessageFormat(true); // 메시지 포맷 규칙 사용
messageSource.setUseCodeAsDefaultMessage(true); // 메시지를 못 찾으면 코드 그 자체를 디폴트 메시지로 사용
messageSource.setFallbackToSystemLocale(true); // 특정 로케일에 대한 파일을 발견하지 못 할 경우, 시스템 로케일로 폴백(resource.yml)
return messageSource;
}
private static class YamlMessageSource extends ResourceBundleMessageSource {
@NotNull
@Override
protected ResourceBundle doGetBundle(@NotNull String basename, @NotNull Locale locale) throws
MissingResourceException {
return ResourceBundle.getBundle(basename, locale, YamlResourceBundle.Control.INSTANCE);
}
}
}
view raw .java hosted with ❤ by GitHub

 

 

YamlMessageSource에서 제공하는 메서드를 간단히 소개하자면 아래와 같습니다.

  • setBaseName: resources 폴더 내 메시지를 찾을 파일 경로
    • 저처럼 "resource"로 설정할 경우 파일 경로는 resources/resource_[Locale].yml이 되며
    • Header 내 Accept-Language가 en일 경우 resource_en.yml,
    • Header 내 Accept-Language가 fr일 경우 resource_fr.yml 파일 내 메시지를 찾게 됩니다.

 

  • setDefaultEncoding: 기본 인코딩 방식
  • setAlwaysUseMessageFormat(): 메세지 포맷 규칙 사용 여부
  • setUseCodeAsDefaultMessage(): 메세지를 못 찾으면 코드 그 자체를 기본 메시지로 사용할지 여부
  • setFallbackToSystemLocale(): 특정 Locale에 대한 파일을 발견하지 못할 경우 fallback 처리로 [base-name].yml을 사용할지 여부
    • base-name을 "message"로 설정했다면 fallback 처리로 message.yml 사용

 

2. LocaleConfiguration

 

다국어 처리를 위해 Spring MVC는 LocaleResolver를 이용하여 웹 요청과 관련된 지역 정보인 Locale을 추출하고 이 Locale 객체를 이용해서 알맞은 언어의 메시지를 선택합니다.

  • Header 내 Accept-Language 정보를 토대로 Locale 설정

 

따라서 LocaleConfiguration에서는 LocaleResolver를 빈으로 설정하고 메인이 국내 서비스이기 때문에 기본 Locale을 KOREAN으로 설정합니다.

 

import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
@Configuration
public class LocaleConfiguration implements WebMvcConfigurer {
/**
* LocaleResolver : 클라이언트의 언어&국가 정보를 인식
* - AcceptHeaderLocaleResolver : 사용자의 Accept-Language 헤더를 이용하여 언어&국가 정보를 인식
*/
@Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.KOREAN); // 언어 & 국가 정보가 없는 경우 한국으로 인식하도록 설정
return resolver;
}
}
view raw .java hosted with ❤ by GitHub

 

 

테스트

앞서 언급한 두 설정 파일을 구현하면 메시지 다국어 처리를 위한 준비는 끝났습니다.

yaml-resource-bundle 라이브러리 적용 시 yml 파일에 map 형식 혹은 list 형식으로 메시지 포맷을 저장할 수 있습니다.

편의상 README에서 제공한 예제를 그대로 사용해서 api로 제공하는 코드를 테스트해보겠습니다.

 

resource.yml (한국어)

 

fruits:
apple: 사과
orange: 오렌지
grape: 포도
colors:
- 빨강
- 주황
- 보라
view raw .yml hosted with ❤ by GitHub

 

 

resource_en.yml (영어)

 

fruits:
apple: Apple
orange: Orange
grape: Grape
colors:
- Red
- Orange
- Purple
view raw .yml hosted with ❤ by GitHub

 

 

ApiController.java

 

package com.tistory.jaimemin.internationalizationmessageyml.controller;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequiredArgsConstructor
public class ApiController {
private final MessageSource messageSource;
/**
* map의 value를 받아오기
*/
@GetMapping("/fruits")
public List<String> getFruits() {
log.info("{}", LocaleContextHolder.getLocale());
return Collections.unmodifiableList(Arrays.asList(
getMessage("fruits.apple"),
getMessage("fruits.orange"),
getMessage("fruits.grape")
));
}
/**
* list 형식으로 받아오기
*/
@GetMapping("/colors")
public List<String> getColors() {
return Collections.unmodifiableList(Arrays.asList(
getMessage("colors[0]"),
getMessage("colors[1]"),
getMessage("colors[2]")
));
}
private String getMessage(String code) {
return getMessage(code, null);
}
private String getMessage(String code, Object[] args) {
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
view raw .java hosted with ❤ by GitHub

 

 

테스트 결과

 

1. map value 받아오는 api (한글)

 

 

2. map value 받아오는 api (영어)

 

 

3. list value 받아오는 api (한글)

 

 

4. list value 받아오는 api (영어)

 

 

 

 

프로젝트 레포지토리

https://github.com/jaimemin/internationalization-message-yml

 

GitHub - jaimemin/internationalization-message-yml: sample code using yaml-resource-bundle library

sample code using yaml-resource-bundle library. Contribute to jaimemin/internationalization-message-yml development by creating an account on GitHub.

github.com

 

postman collection

 

메세지 다국어 처리
0.00MB

 

 

 

 

참고

https://github.com/ttasjwi/trilo-be

 

GitHub - ttasjwi/trilo-be

Contribute to ttasjwi/trilo-be development by creating an account on GitHub.

github.com

https://velog.io/@junyoungs7/LocaleResolver%EB%9E%80

 

velog

 

velog.io

https://engkimbs.tistory.com/entry/Spring-%EB%A9%94%EC%84%B8%EC%A7%80%EC%86%8C%EC%8A%A4MessageSource%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%A9%94%EC%84%B8%EC%A7%80-%EA%B5%AD%EC%A0%9C%ED%99%94-%EB%A9%94%EC%84%B8%EC%A7%80-%EC%86%8C%EC%8A%A4-%EB%A6%AC%EB%A1%9C%EB%94%A9MessageSource-Reloading

 

[Spring] 메세지소스(MessageSource)를 통한 메세지 국제화, 메세지 소스 리로딩(MessageSource Reloading)

| 스프링 메세지소스(Spring MessageSource) 스프링 메세지 소스(Spring MeesageSource)는 국제화(i18n)을 제공하는 인터페이스다. 메세지 설정 파일을 모아놓고 각 국가마다 로컬라이징을 함으로서 쉽게 각

engkimbs.tistory.com

 

반응형