반응형
메시지, 국제화
메시지
: 여러 화면에서 동일한 명칭으로 하드 코딩되어 있는 것을 한 곳에서 관리하는 기능을 의미한다. 예를 들어 messages.properties
라는 메시지 관리용 파일을 만들고 각 HTML은 해당 데이터를 key 값으로 불러서 사용하는 것이다.
다음 예시를 살펴 보자.
item = 상품
item.id = 상품 ID
item.itemName = 상품명
item.price = 가격
item.quantity = 수량
- messages.properties라는 메시지 관리용 파일
<label for="itemName" th:text="#{item.itemName}"></label>
- 해당
label
을 각 HTML에서 렌더링하여 사용한다.
국제화
: 메시지에서 설정한 파일을 각 나라별로 관리하여 서비스를 제공하는 것을 국제화라고 한다. 예를 들어 message_en.properties
와 message_ko.properties
를 사용하여 국제화를 적용시킬 수 있다.
나라 별 접근 확인은 HTTP의 accept-language
를 사용하거나, 사용자가 직접 언어를 선택하도록 하고 쿠키 등을 사용해서 처리할 수 있다.
스프링은 기본적인 메시지와 국제화 기능을 모두 제공한다. 또한, 타임리프도 스프링이 제공하는 국제화 기능을 편리하게 통합해서 제공한다. 지금부터 스프링이 제공하는 메시지와 국제화 기능을 알아보자.
스프링 메시지 소스 설정
- 스프링은 기본적인 메시지 관리 기능을 제공한다. 메시지 관리 기능을 사용하려면
MessageSource
를 스프링 빈으로 등록하면 되는데 인터페이스로 만들어져 있다. 즉, 구현체인ResourceBundleMessageSource
를 스프링 빈으로 등록하면 된다. - 스프링 부트는
MessageSource
를 자동으로 스프링 빈으로 등록해준다. 별도의 설정을 하지 않아도 messages라는 이이름으로spring.messages.basename=messages
가 기본적으로 등록되어 있으며resources
디렉토리 바로 밑에messages_en.properties
,messages_ko.properties
등 파일만 등록하면 자동으로 인식된다. - 스프링 부트에서
MessageSource
를 추가로 사용하려면application.properties
에spring.messages.basename=messages,config.i18n.messages
와 같이 경로를 넣어주면 된다.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.MessageSource;
import static org.assertj.core.api.Assertions.*;
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void helloMessage() {
String result = ms.getMessage("hello", null, null);
assertThat(result).isEqualTo("안녕");
}
}
- 테스트 코드를 통해 메시지 코드를 확인해 보자.
locale
정보가 없으면 기본 파일인messages.properties
를 조회한다.
@Test
void notFoundMessageCode() {
assertThatThrownBy(() -> ms.getMessage("no_code", null, null))
.isInstanceOf(NoSuchMessageException.class);
}
@Test
void notFoundMessageCodeDefaultMessage() {
String result = ms.getMessage("no_code", null, "기본 메시지", null);
assertThat(result).isEqualTo("기본 메시지");
}
@Test
void argumentMessage() {
String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(result).isEqualTo("안녕 Spring");
}
- 메시지가 없는 경우
NoSuchMessageException
이 발생한다. - 메시지가 없어도 세번째 파라미터인
defaultMessage
를 사용하면 기본 메시지가 반환된다. {0}
부분은 매개변수를 전달해서 치환할 수 있다. 단,ms.getMessage
에서 오브젝트 배열로 반환해줘야 한다.
@Test
void defaultLang() {
assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
@Test
void enLang() {
assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
}
- 국제화 테스트 :
Locale.국가
를 통해 확인할 수 있다.Locale.ENGLISH
는messages_en
을 찾아서 사용
웹 애플리케이션에 메시지 적용하기
hello=안녕
hello.name=안녕 {0}
label.item=상품
label.item.id=상품 ID
label.item.itemName=상품명
label.item.price=가격
label.item.quantity=수량
page.items=상품 목록
page.item=상품 상세
page.addItem=상품 등록
page.updateItem=상품 수정
button.save=저장
button.cancel=취소
message.properties
에 메시지를 추가하자.
<div th:text="#{label.item}"></div>
<div>상품</div>
- 타임리프의 메시지 표현식인
#{...}
를 사용하면 스프링 메시지를 편리하게 조회할 수 있다.
웹 애플리케이션에 국제화 적용하기
hello=hello
hello.name=hello {0}
label.item=Item
label.item.id=Item ID
label.item.itemName=Item Name
label.item.price=price
label.item.quantity=quantity
page.items=Item List
page.item=Item Detail
page.addItem=Item Add
page.updateItem=Item Update
button.save=Save
button.cancel=Cancel
- 기존의 HTML에 메시지 적용을 하면서
#{...}
처리를 해두었기 때문에 국제화 작업은 거의 끝났다.
- 크롬 브라우저에서 설정 - 언어 - 영어를 상단으로 올리고 새로고침하면
en
으로 렌더링 되는 것을 볼 수 있다.
Request Headers
를 보면 허용 언어의 우선 순위가 지정되어 있음을 볼 수 있다. 즉, 방금 했던 크롬에서의 언어 설정은 해당 언어의 우선 순위를 바꾸는 것과 동일하다.
LocaleResolver
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request);
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse
response, @Nullable Locale locale);
}
- 스프링은
Locale
선택 방식을 변경할 수 있도록LocaleResolver
라는 인터페이스를 제공하는데, 스프링 부트는 기본으로Accept-Language
를 활용하는AcceptHeaderLocaleResolver
를 사용한다. Locale
선택 방식을 변경하려면 해당 구현체를 변경해서 쿠키나 세션 기반의Locale
선택 기능을 사용할 수 있다. 예를 들면 고객이 직접Locale
을 선택하도록 하는 것이다.
본 포스팅은 인프런 - 김영한님의 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술을 참고하였습니다.
반응형