1. 메시지
메시지를 한 곳에서 관리하도록 하는 기능을 메시지 기능이라 한다.
예를 들어서 messages.properties라는 메시지 관리용 파일을 만들고
각 HTML들은 다음과 같이 해당 데이터를 key값으로 불러서 사용하는 것이다.
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량
<label for="itemName" th:text="#{item.itemName}"></label>
2. 국제화
메시지에서 설명한 메시지 파일(message.properties)을 각 나라별로 별도로 관리하면 서비스를 국제화 할 수 있다.
//messages_en.properties
item=Item
item.id=Item ID
item.itemName=Item Name
item.price=price
item.quantity=quantity
//messages_ko.properties
item=상품
item.id=상품 ID
item.itemName=상품명
item.price=가격
item.quantity=수량
한국에서 접근한 것인지 영어에서 접근한 것인지는 인식하는 방법은 HTTP accept-language헤더 값을 사용하거나 사용자가 직접 언어를 선택하도록 하고, 쿠키 등을 사용해서 처리하면 된다.
메시지와 국제화 기능을 직접 구현할 수도 있겠지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공한다.
그리고 타임리프도 스프링이 제공하는 메시지와 국제화 기능을 편리하게 통합해서 제공한다.
3. 스프링 메시지 소스 설정
메시지 관리 기능을 사용하려면 스프링이 제공하는 MessageSource를 스프링 빈으로 등록하면 되는데, MessageSource는 인터페이스이다.
따라서 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하면 된다.
스프링 부트를 사용하면 스프링 부트가 MessageSource를 자동으로 스프링 빈으로 등록한다.
//application.properties
spring.messages.basename=messages
MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 message라는 이름으로 기본 등록된다.
따라서 messages_en.properties, messages_ko.properties, messages.properties 파일만 등록하면 자동으로 인식된다.
4. 스프링 메시지 소스 사용
//messages.properties
hello=안녕
hello.name=안녕 {0}
//messages_en.properties
hello=hello
hello.name=hello {0}
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void helloMessage() {
String result = ms.getMessage("hello", null, null);
assertThat(result).isEqualTo("안녕");
}
@Test
void notFoundMessageCode(){
assertThatThrownBy(() -> ms.getMessage("no-code", null, null))
.isInstanceOf(NoSuchMessageException.class);
}
@Test
void notFoundMessageCodeDefaultMessage(){
String result = ms.getMessage("no-code", null, "default", null);
assertThat(result).isEqualTo("default");
}
@Test
void argumentMessage() {
String message = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(message).isEqualTo("안녕 Spring");
}
@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.getDefault()를 호출해서 시스템의 기본 로케일을 사용한다.
예) locale = null인 경우 ㅡ> 시스템 기본 locale이 ko_KR이므로 messages_ko.properties 조회 시도 ㅡ> 조회 실패
ㅡ> messages.properties 조회
LocaleResolver
스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver라는 인터페이스를 제공하는데, 스프링 부트는 기본으로 Accept-language를 활용하는 AcceptHeaderLocaleResolver를 사용한다.
만약 Locale 선택 방식을 변경하려면 LocaleResolver의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택 기능을 사용할 수 있다.
예를 들어서 고객이 직접 Locale을 선택하도록 하는 것이다.
5. 웹 애플리케이션에 메시지 적용
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 class="container">
<div class="py-5 text-center">
<h2 th:text="#{page.addItem}">상품 등록</h2>
</div>
<form action="item.html" th:action th:object="${item}" method="post">
<div>
<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
<input type="text" id="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요">
</div>
<div>
<label for="price" th:text="#{label.item.price}">가격</label>
<input type="text" id="price" th:field="*{price}" class="form-control" placeholder="가격을 입력하세요">
</div>
<div>
<label for="quantity" th:text="#{label.item.quantity}">수량</label>
<input type="text" id="quantity" th:field="*{quantity}" class="form-control" placeholder="수량을 입력하세요">
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<button class="w-100 btn btn-primary btn-lg" type="submit" th:text="#{button.save}">저장</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='items.html'"
th:onclick="|location.href='@{/message/items}'|"
type="button" th:text="#{button.cancel}">취소</button>
</div>
</div>
</form>
</div>
6. 웹 애플리케이션에 국제화 적용
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
'Spring' 카테고리의 다른 글
[스프링 MVC 2편 - 백엔드 웹 개발 활용 기술] 02. 타임리프 스프링 통합과 폼 (0) | 2025.03.03 |
---|---|
[스프링 MVC 2편 - 백엔드 웹 개발 활용 기술] 01. 타임리프 기본기능 (1) | 2025.03.01 |
[스프링 MVC - 백엔드 웹 개발 핵심 기술] 07. 웹 페이지 만들기 (0) | 2025.02.19 |
[스프링 MVC - 백엔드 웹 개발 핵심 기술] 06. 스프링 MVC 기본 기능 (0) | 2025.02.17 |
[스프링 MVC - 백엔드 웹 개발 핵심 기술] 05. 스프링 MVC 구조 이해 (0) | 2025.02.13 |