스프링 클라우드 마이크로서비스에서 국제화(I18n) 설정하기

국제화(I18n)란

국제화(Internationalization, I18n)는 다양한 언어와 문화 환경에 적응할 수 있도록 제품을 설계하고 개발하는 과정을 의미합니다. 이는 기본 버전의 제품을 생성한 후, 구성 및 리소스 파일을 통해 다양한 언어와 지역에 대한 지원을 추가하는 방식으로 이루어집니다.

이렇게 하면 제품이 새로운 지역이나 언어 환경에서 사용되어야 할 때, 제품 자체의 코드를 수정할 필요 없이 해당 리소스 파일을 추가하거나 업데이트하기만 하면 됩니다.

"I18n"은 "Internationalization"의 약어입니다. "I"와 "n" 사이에 18개의 문자가 있기 때문에 이런 약어가 사용됩니다. 비슷한 예로 "K8s"가 있습니다.

스프링 부트 국제화 구현

Java 백엔드에서 I18n는 주로 오류 메시지에 적용되며, 스프링 부트는 I18n에 대한 기본 지원을 제공합니다. 사용 방법은 매우 간단하며 공식 문서를 참고할 수 있습니다.

국제화 리소스 파일 추가

스프링 부트는 기본적으로 classpath/resource/messages 디렉토리의 국제화 리소스 파일을 읽습니다. 다음 설정을 통해 이를 변경할 수 있습니다:

spring.messages.basename=messages<br></br>

IDE를 사용하여 국제화 리소스 파일을 생성하는 방법은 다음과 같습니다:

생성이 완료되면 resources 디렉토리에 다음과 같은 국제화 리소스 파일이 표시됩니다. 예시에서는 개발 시 흔히 발생하는 로그인 오류 메시지를 정의했습니다.

유틸리티 클래스 생성

유틸리티 클래스를 생성하는 목적은 국제화 정보를 쉽게 얻기 위함입니다.

public class LocaleMessageHelper {<br></br> public static String getLocalizedMessage(String errorCode) {<br></br>         try {<br></br>           // 스프링 부트가 제공하는 MessageSource의 기본 구현체<br></br>             MessageSource messageSource = ApplicationContextProvider.getBean("messageSource");<br></br>             // 스프링 부트에서 요청 컨텍스트 언어 정보 가져오기<br></br>             Locale currentLocale = LocaleContextHolder.getLocale();<br></br>             // 프로젝트에서는 중국어와 영어만 사용하므로, 중국어가 아닌 경우 기본으로 영어 사용<br></br>             // 여기서는 간체 중국어 정의: Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};<br></br>             if (Arrays.stream(LocaleConstants.SIMPLIFIED_CHINESE).toList().contains(currentLocale)) {<br></br>                 currentLocale = Locale.SIMPLIFIED_CHINESE;<br></br>             } else {<br></br>                currentLocale = Locale.US;<br></br>             }<br></br>            return messageSource.getMessage(errorCode, null, currentLocale);<br></br>         } catch (Exception e) {<br></br>             log.error("국제화 내용 가져오기 중 오류 발생", e);<br></br>             // 국제화 정보 가져오기 실패 시 원본 코드 반환<br></br>             return errorCode;<br></br>         }<br></br>     }<br></br>}<br></br>

API 응답 클래스 정의

@Data<br></br>public class ApiResponse<T> implements Serializable {<br></br><br></br>    private static final long serialVersionUID = 1L;<br></br><br></br>    /** 상태 코드 */<br></br>    private String status;<br></br><br></br>    /** 응답 메시지 */<br></br>    private String responseMessage;<br></br><br></br>    /** 응답 데이터 */<br></br>    private T responseData;<br></br>    <br></br>    public String getResponseMessage(){<br></br>     if (StringUtils.isNotEmpty(this.status)) {<br></br>       // I18n 메시지 가져오기<br></br>      return LocaleMessageHelper.getLocalizedMessage(this.status)<br></br>     }<br></br>     return this.responseMessage;<br></br>    }<br></br>    <br></br>    // 기타 메소드 생략..<br></br>}<br></br>

요청 헤더에 언어 코드 추가

curl -H "Accept-Language: zh-CN" http://example.com<br></br>

스프링 클라우드에서의 국제화 설정

위 내용은 단일 스프링 부트 프로젝트에서 I18n를 구현하는 간단한 과정입니다. 하지만 스프링 클라우드 환경에서는 일반적으로 여러 서비스(스프링 부트 프로젝트)가 존재합니다. 일반적으로 공통 모듈(common) 프로젝트를 만들어 POJO와 일반적인 유틸리티 클래스, 상수 클래스 등을 패키징한 후 JAR 파일로 만들어 다른 비즈니스 서비스들이 이를 의존하게 하는 방식으로 기능을 재사용합니다. 일반적으로 사용자 ID가 비어있을 수 없음과 같은 일반적인 오류 정보를 common 프로젝트에 배치하는데, 이러한 일반 오류 정보를 I18n로 어떻게 설정할 수 있을까요?

위에서 설명한 대로 common 프로젝트를 JAR 파일로 패키징하여 다른 비즈니스 서비스에서 사용하면, 다른 서비스가 common 의존성을 가져온 후 common과 비즈니스 서비스는 동일한 스프링 컨테이너에 위치하게 됩니다. 이때 위에서 설명한 I18n 설정은 common 내부의 I18n 설정을 읽을 수 없습니다(위에서 스프링 부트는 기본적으로 프로젝트 classpath/resource 아래의 구성 파일을 읽는다고 설명했습니다). 따라서 우리는 custom MessageSource를 정의하여 common의 I8n 설정을 읽을 수 있습니다.

  1. 먼저, common 프로젝트의 resource 디렉토리에 I8n 구성 파일을 생성합니다. 위에서 설명한 방법과 동일하지만, 비즈니스 서비스와 동일한 스프링 컨테이너에 있으므로 리소스 이름을 구분해야 합니다. 일단 common_messages라고 명명하겠습니다.

Untitled1. 다음으로, custom MessageSource Bean을 구성하고 설정한 common_messages를 읽도록 합니다.

@Bean(name = "commonMessageSource")<br></br>public ResourceBundleMessageSource customMessageSource() throws IOException {<br></br>    ResourceBundleMessageSource source = new ResourceBundleMessageSource();<br></br>    source.setDefaultEncoding(StandardCharsets.UTF_8.name());<br></br>    source.setBasename("common_messages");<br></br>    return source;<br></br>}<br></br>
  1. 마지막으로, LocaleMessageHelper 로직을 조정하여 비즈니스 서비스 자체의 I18n를 먼저 읽고, 없으면 common I18n에서 가져오며, 그래도 없으면 원본 code를 반환하도록 합니다.
public class LocaleMessageHelper { public static String getLocalizedMessage(String errorCode) {         try {           // 스프링 부트가 제공하는 MessageSource의 기본 구현체             MessageSource messageSource = ApplicationContextProvider.getBean("messageSource");             // 스프링 부트에서 요청 컨텍스트 언어 정보 가져오기             Locale currentLocale = LocaleContextHolder.getLocale();             // 프로젝트에서는 중국어와 영어만 사용하므로, 중국어가 아닌 경우 기본으로 영어 사용             // 여기서는 간체 중국어 정의: Locale[] SIMPLIFIED_CHINESE = {Locale.CHINESE, Locale.CHINA, Locale.SIMPLIFIED_CHINESE, Locale.PRC};             if (Arrays.stream(LocaleConstants.SIMPLIFIED_CHINESE).toList().contains(currentLocale)) {                 currentLocale = Locale.SIMPLIFIED_CHINESE;             } else {                currentLocale = Locale.US;             }            try{              // 먼저 비즈니스 서비스 자체의 I18n 설정 읽기             return messageSource.getMessage(errorCode, null, currentLocale);            }catch (NoSuchMessageException e) {                // 해당 메시지가 없으면 common에서 I18n 읽기              ResourceBundleMessageSource commonMessageSource = ApplicationContextProvider.getBean("commonMessageSource");                return commonMessageSource.getMessage(errorCode, null, currentLocale);            }         } catch (Exception e) {             log.error("국제화 내용 가져오기 중 오류 발생", e);             // 국제화 정보 가져오기 실패 시 원본 코드 반환             return errorCode;         }     }}
``

태그: 스프링 클라우드 마이크로서비스 국제화 I18n 스프링 부트

5월 20일 14:35에 게시됨