이번에는 메시지, 국제화 기능에 대해 알아보자!
화면에서 공통으로 사용되는 다양한 메세지를 한 곳에서 관리하도록 하는 기능을 메세지 기능이라 한다.
메세지 기능을 사용하지 않을 경우, 우리는 모든 메세지를 각각 하드코딩으로 입력해야한다.
💡 하드 코딩
데이터를 코드 내부에 직접 입력하는 것이다.
<label for="itemName">상품명</label>
하드코딩은 값을 바로 확인할 수 있지만, 유지보수가 어렵다는 단점이 있다!
messages.properteis
라는 메시지 관리용 파일을 만든 뒤,
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량
각 HTML에서 해당 데이터를 key
값으로 불러서 사용하여 메시지 기능을 사용할 수 있다!
addForm.html
<label for="itemName" th:text="#{item.itemName}"></label>
editForm.html
<label for="itemName" th:text="#{item.itemName}"></label>
메시지 파일(messages.properties
)을 각 나라별로 별도로 관리하여 서비스를 국제화할 수 있다.
messages_en.properties
)item=Item
item.id=Item ID
item.itemName=Item Name
item.price=price
item.quantity=quantity
meesages_ko.properties
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량
👨🏼 (미국인) → messages_en.properties
사용
👨🏻 (한국인) → messages_ko.properties
사용
🙋🏻♀️ 근데 제가 한국어를 원하는지, 영어를 원하는지는 어떻게 아나요?
HTTP accept-language
헤더 값을 사용을 활용해서 어떤 언어를 원하는지 조사하고 쿠키 등을 사용해서 처리하면 된다.
스프링은 기본적인 메시지 관리 기능을 제공한다.
스프링 부트는 프레임워크 자체적으로 MessageSource
를 자동으로 스프링 빈으로 등록해준다.
spring.messages.basename=messages
MessageSource
를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages
라는 이름으로 기본 등록된다.
messages_en.properties
, messages_ko.properties
, messages.properties
파일만 등록하면 자동으로 인식된다.
messages.properties
: 기본값으로 사용 (한글)messages_en.properties
: 영어 국제화 사용스프링이 제공하는 메시지 소스를 어떻게 사용하는지 테스트를 통해 알아보자!
MessageSourceTest
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void helloMessage() {
String result = ms.getMessage("hello", null, null);
assertThat(result).isEqualTo("안녕");
}
}
ms.getMessage("hello", null, null)
hello
null
null
hello
, 나머지 값들은 null
입력locale
정보 ❌ basename
에서 설정한 기본 이름 메시지 파일 조회! (basename
으로 messages
지정)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("기본 메시지");
}
NoSuchMessageException
발생defaultMessage
)를 사용시 기본 메시지가 반환됨!@Test
void argumentMessage() {
String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(result).isEqualTo("안녕 Spring");
}
메시지의 {0}
부분은 매개변수를 전달해서 치환할 수 있다.
hello.name=안녕 {0}
→ Spring
을 매개변수로 전달 → 안녕 Spring
locale 정보를 기반으로 국제화 파일을 선택한다.
en_US
의 경우messages_en_US
→ messages_en
→ messages
순서로 찾는다.Locale
에 맞추어 구체적인 것이 있으면 구체적인 것을 찾고, 없으면 디폴트를 찾는다.@Test
void defaultLang() {
assertThat(ms.getMessage("hello", null, null)).isEqualTo("안녕");
assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
ms.getMessage("hello", null, null)
: locale 정보가 없으므로 messages
사용ms.getMessage("hello", null, Locale.KOREA)
: locale 정보가 있지만, message_ko
가 없으므로 messages
사용@Test
void enLang() {
assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
}
ms.getMessage("hello", null, Locale.ENGLISH)
: locale 정보가 Locale.ENGLISH
이므로messages_en
을 찾아서 사용테스트 성공~!
실제 웹 애플리케이션에 메시지를 적용해보자!
messages.properties
- 메시지 추가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=취소
타임리프의 메시지 표현식 #{...}
를 사용하면 스프링의 메시지를 편리하게 조회할 수 있다.
<div th:text="#{label.item}"></h2>
<div>상품</div>
이번에는 웹 애플리케이션에 국제화를 적용해보자!
messages_en.properties
- 영어 메시지 추가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
웹 브라우저의 언어 설정 값을 변경하면서 국제화 적용을 확인해보자!
크롬 브라우저 → 설정 → 언어에서 영어를 제일 위로 위치시킨다.
웹 브라우저의 언어 설정 값을 변경하면, 요청시 Accept-Language
의 값이 변경된다.
Accept-Language
는 클라이언트가 서버에 기대하는 언어 정보를 담아서 요청하는 HTTP 요청 헤더이다.
영어로 잘 나온다!