기존에 사용하던 상품 등록 폼을 코드로 보자
<form action="item.html" th:action th:object = "${item}" method="post">
<div>
<label for="itemName">상품명</label>
<input type="text" id="itemName" th:field = "*{itemName}"
class="form-control" placeholder="이름을 입력하세요">
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" th:field = "*{price}"
class="form-control" placeholder="가격을 입력하세요">
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" th:field = "*{quantity}"
class="form-control" placeholder="수량을 입력하세요">
</div>
당연히 상품명, 가격 등 변수들은 ${item}
을 통해 받아와 변수를 통해 뿌려주고 있지만,
라벨에 해당하는 상품명, 가격, 수량이라는 이름은 하드코딩 되어있는 것을 볼 수 있다.
이러한 코딩은 당연히 유연하지 못해 변경에 취약하다.
이것을 유연하게 바꿔보고 언어별 설정까지 살펴보자
메시지 관리 기능을 사용하려면 스프링이 제공하는 MessageSource 를 스프링 빈으로 등록하면 되는데, MessageSource 는 인터페이스이다.
따라서 구현체인 ResourceBundleMessageSource 를 스프링 빈으로 등록하면 된다.
하지만 킹갓 스프링부트 를 사용하면 스프링 부트가 MessageSource 를 자동으로 스프링 빈으로 등록한다.
스프링 부트에서 기본 값으로
spring.messages.basename=messages
를 사용하며
MessageSource 를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages 라는 이름으로 기본 등록된다. 따라서 messages_en.properties , messages_ko.properties , messages.properties 파일만 등록하면 자동으로 인식된다.
이에 따라 메시지 파일을 만든다면,
messages.properties 파일을 기본 값으로 사용하고,
messages_en.properties 처럼 뒤에 언어 설정을 붙여서 국제화에 사용할 수 있다.
messages.properities 파일 예시
MessageSource 인터페이스는 아래와 같다
public interface MessageSource {
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
getMessage의 파라미터는 아래와 같다.
타임리프의 메시지 표현식 #{...} 를 사용하면 스프링의 메시지를 편리하게 조회할 수 있다.
예를 들어서 방금 등록한 상품이라는 이름을 조회하려면 #{label.item} 이라고 하면 된다.
기존 예시의 하드 코딩된 HTML을 아래와 같이 바꿔주면 된다.
<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>
Accept-Language 의 값을 통해 언어를 설정하게 되는데,
Accept-Language 는 클라이언트가 서버에 기대하는 언어 정보를 담아서 요청하는 HTTP 요청 헤더이다.
사실 이미 타임리프로 HTML 파일 설정을 맞췄기 때문에,
messages_en.properties 파일만 만들고 헤더값을 조정해주면
렌더링이 잘 되는 것을 확인할 수 있다.
스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver 라는 인터페이스를 제공하는데,
스프링 부트는 기본으로 Accept-Language 를 활용하는 AcceptHeaderLocaleResolver 를 사용한다.
만약 Locale 선택 방식을 변경하려면 LocaleResolver 의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택 기능을 사용할 수 있다.
예를 들어서 고객이 직접 Locale 을 선택하도록 하는 것이다.
관련해서 LocaleResolver 를 검색하면 수 많은 예제가 나온다니 필요할 때 도전해보자