본문 바로가기
Web/spring study

[Spring] 메시지, 국제화

by 장인이 2024. 1. 18.

1. 개요

 개발을 하다 보면, 전반적으로 단어를 수정해야 할 경우가 있다. (ex) 엄마 -> 어머님) 여러 화면에 단어를 변경하려면, 직접 화면들을 찾아가면서 모두 변경해야 한다. 예제 수준이라면 문제가 되지 않지만, 화면이 수십개 이상이라면 파일을 모두 고쳐야 한다.

 이런 상황을 대비하여 다양한 메시지들을 한 곳에서 관리하는 기능을 메시지 기능이라고 하며, 해당 브라우저의 언어 설정에 따라 사이트의 언어가 바뀌게 하는 기능을 국제화라고 한다. 이 두 가지 기능에 대해 알아보자.

 

 

2. 스프링 메시지 소스 설정

 물론 메시지, 국제화 기능을 직접 구현하는 것도 가능하다. 하지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공한다. 또한, 타임리프도 이를 편리하게 통합해서 제공한다.

 

 메시지 관리 기능을 사용하려면, 스프링이 제공하는 MessageSource라는 인터페이스를 스프링 빈으로 등록하면 된다.

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("messages", "errors");
    messageSource.setDefaultEncoding("utf-8");
    return messageSource;
}

 

 MessageSource는 인터페이스이므로, 구현체인 ResourceBundleMessageSource를 사용한다.

 여기서 setBasenames()을 통해 설정 파일의 이름을 저장한다. 위의 예시처럼 messages로 지정하면, messages.properties 파일을 읽어서 사용한다. 파일 위치는 /resources/messages.properties에 두면 되고, 여러 파일을 한번에 지정할 수 있다.

  만일에 여기서 국제화 기능을 적용하려면, messages_ko.properties, messages_en.properties와 같이 파일명에 언어 정보를 추가하면 된다.

 

 

3. 스프링 부트 메시지 소스 설정

 사실, 스프링 부트를 사용하면 개발자가 직접 MessageSource를 등록하지 않을 경우, messages라는 이름으로 기본 등록된다! 따라서 messages.properties, messages_ko.properties, messages_en.properties와 같은 파일만 등록하면 자동으로 인식된다.

 

 만일 메시지 소스 위치를 변경하고 싶다면, application.properties에 다음과 같이 입력하면 된다. 여러개를 입력할 수 있으며, 기본값은 messages이다.

spring.messages.basename=messages,config.i18n.messages

 

 

4. 메시지 파일 만들고 테스트

 메시지 파일을 만들고, 국제화 기능도 한번에 확인해 보자.

 

/resources/messages.properties

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

 

/resources/messages_en.properties

hello=hello
hello.name=hello {0}

 

이를 직접 가져와서, 테스트해 볼 수 있다.

@SpringBootTest
public class MessageSourceTest {

    @Autowired
    MessageSource ms; //주입받기

    @Test //1.
    void helloMessage() {
        String result = ms.getMessage("hello", null, null);
        assertThat(result).isEqualTo("안녕");
    }
    
    @Test //2.
    void notFoundMessageCode() {
    	assertThatThrownBy(() -> ms.getMessage("no_code", null, null))
        		.isInstanceOf(NoSuchMessageException.class);
    }
    
    @Test //3.
    void notFoundMessageCodeDefaultMessage() {
    	String result = ms.getMessage("no_code", null, "기본 메시지", null);
        assertThat(result).isEqualTo("기본 메시지");
    }
    
    @Test //4.
    void argumentMessage() {
    	String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
        assertThat(result).isEqualTo("안녕 Spring");
    }
    
    @Test //5.
    void defaultLang() {
    	assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
        assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
        assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
    }

}

 

ms.getMessage(code, args, locale)

code: 메시지 코드 입력 //1.

- args: argument가 있는 경우, 입력 //4.

- locale: locale 정보 입력. 없으면 시스템의 기본 로케일을 사용하며, 없을 경우에는 messages.properties를 사용 //5.

 

만일에 메시지가 없는 경우에는 NoSuchMessageException이 발생한다. //2.

ms.getMessage(code, args, defaultMessage, locale)

defaultMessage: 기본 메시지 설정, 메시지가 없어도 예외 발생이 아닌, 기본 메시지가 반환된다. //3. 

 

 

5. 타임리프에 메시지, 국제화 적용하기

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

<div th:text="#{hello}"></div>
<div th:text="#{hello.name(${item.itemName})}"></div>

 

 이렇게 하면 끝난다! 국제화가 필요한 경우, messages_en.properties 와 같이 메시지를 추가하기만 하면, 자동으로 적용된다. 스프링은 언어 선택시 기본으로 클라이언트 HTTP 헤더 중 Accept-Language 헤더의 값을 사용한다.

(Accept-Language 헤더?)

 

 만일 Locale 선택 방식을 변경하려면, LocaleResolver의 구현체를 직접 변경해서 쿠키나 세션 기반의 Locale 선택 기능을 사용할 수 있다.

 

 


위 내용은 김영한 님의 인프런 강의 "스프링 MVC 2편 - 백엔드 웹 개발 핵심 기술"의 내용과 강의자료를 토대로 작성된 게시글입니다.

강의 링크:

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2

 

 

 

 

 

댓글