개요
진행 중인 프로젝트에 다국어 처리를 추가해야 하는데, 공식 문서에서 제시한 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); | |
} | |
} | |
} |
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; | |
} | |
} |
테스트
앞서 언급한 두 설정 파일을 구현하면 메시지 다국어 처리를 위한 준비는 끝났습니다.
yaml-resource-bundle 라이브러리 적용 시 yml 파일에 map 형식 혹은 list 형식으로 메시지 포맷을 저장할 수 있습니다.
편의상 README에서 제공한 예제를 그대로 사용해서 api로 제공하는 코드를 테스트해보겠습니다.
resource.yml (한국어)
fruits: | |
apple: 사과 | |
orange: 오렌지 | |
grape: 포도 | |
colors: | |
- 빨강 | |
- 주황 | |
- 보라 |
resource_en.yml (영어)
fruits: | |
apple: Apple | |
orange: Orange | |
grape: Grape | |
colors: | |
- Red | |
- Orange | |
- Purple |
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()); | |
} | |
} |
테스트 결과
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
참고
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
[Spring] 메세지소스(MessageSource)를 통한 메세지 국제화, 메세지 소스 리로딩(MessageSource Reloading)
| 스프링 메세지소스(Spring MessageSource) 스프링 메세지 소스(Spring MeesageSource)는 국제화(i18n)을 제공하는 인터페이스다. 메세지 설정 파일을 모아놓고 각 국가마다 로컬라이징을 함으로서 쉽게 각
engkimbs.tistory.com
'리서치' 카테고리의 다른 글
[SpringBoot] Springdoc Swagger 적용 (2) | 2024.05.28 |
---|---|
[SpringBoot] JPA 쿼리 성능 감시 가이드 (0) | 2024.03.12 |
[Springboot] Jpa 프로젝트에 jOOQ 도입 (6) | 2023.10.03 |
[Springboot] 멀티 데이터소스 (MyBatis, JPA) (11) | 2023.03.25 |
[MSA] CQRS 패턴과 실제 적용 사례 (4) | 2022.10.31 |