메세지
화면에서 공통으로 사용되는 다양한 메세지를 한 곳에서 관리하도록 하는 기능을 메세지 기능이라고 합니다.
메세지 기능을 사용하지 않을 경우 우리는 모든 메세지를 각각 하드코딩으로 입력해야 합니다.
<div>
<label for="itemId">상품 ID</label>
<input type="text" id="itemId" name="itemId" class="form-control" value="1" th:value="${item.id}" readonly>
</div>
<div>
<label for="itemName">상품명</label>
<input type="text" id="itemName" name="itemName" class="form-control" value="상품A" th:value="${item.itemName}" readonly>
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" name="price" class="form-control" value="10000" th:value="${item.price}" readonly>
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" name="quantity" class="form-control" value="10" th:value="${item.quantity}" readonly>
</div>
아이템 상세를 보여주는 위 HTML 태그들에는 각각 하드코딩으로 상품ID, 상품명, 가격, 수량이 적혀있습니다.
또한 해당 명칭들은 나머지 다른 많은 페이지에서 공통으로 쓰이고 있다고 할 대 기획 변경으로 상품명을 제품명으로 바꿔야 한다면 어떻게 할까요? 메세지 기능을 사용하지 않았다면 모든 소스파일에서 하나하나 상품명이라 적혀있는 곳을 찾아 제품명이라 바꿔주어야 합니다.
하지만 메세지 기능을 사용했다면 다음과 같이 메세지를 변수화 하여 key 값으로 불러 사용할 수 있습니다.
message.properties
item.itemName= 제품명
<label for="itemName" th:text="#{item.itemName}"></label>
이제 메세지를 한 곳에 모아서 기획자의 기획변경에도 어려움없이 메세지를 바꿀 수 있습니다.
국제화
만약 서비스가 제공되어야하는 곳이 다른 언어권이라면 어떻게 해야할까요? 메세지 내용을 바꾸기엔 기존 서비스 언어권 국가에는 그대로 제공이 되어야 합니다. 이럴 경우 메세지 파일을 각 나라별로 별도로 관리하여 국제화 기능을 제공할 수 있습니다.
예를 들어 한국과 영어 두 언어가 제공되어야 한다면 다음과 같이 두 개의 파일을 만들어 분류할 수 있습니다.
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= 수량
이제 영어를 사용하는 사용자는 messages_en.properties 를 한국어를 사용하는 사용자는 messages_ko.properties 를 사용하도록 개발하면 됩니다.
서버에서는 사용자가 한국어를 원하는지 영어를 원하는지 구분하기 위해서 accept-language 헤더 값을 이용하거나 사용자가 직접 언어를 선택하게 한 뒤 이를 쿠키등을 사용해 처리하면 됩니다.
스프링에서 메세지 소스 설정
스프링은 기본적인 메세지 관리 기능을 제공하는데, 스프링 부트는 프레임워크 자체적으로 MessageSource 를 자동으로 스프링 빈으로 등록을 해줍니다.
설정해보기
messages.properties
hello=안녕
hello.name= 안녕 {0}
messages_en.properties
hello= hello
hello.name= hello {0}
IntelliJ 를 사용한다면 여러 messages 설정이 묶여서 Resoure Bundle 'messages' 로 자동으로 뭉쳐집니다.
그리고 해당 경로를 보면 다음과 같이 나오는 것을 볼 수 있습니다.
스프링에서 메시지 소스 사용해보기
스프링 프로젝트는 구동시 자동(혹은 수동) 으로 스프링 빈으로 MessageSource 가 등록이 됩니다.
이 빈을 통해 메세지 기능을 사용할 수 있으며 테스트를 할 때 필요한 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;
}
이러한 코드는 아래 예시를 보면 이해가 되실 것입니다.
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void helloMessage() {
String hello = ms.getMessage("hello", null, null);
Assertions.assertThat(hello).isEqualTo("안녕");
}
@Test
void notFoundMessageCode() {
/*assertThatThrownBy(() -> ms.getMessage("no_content", null, null))
.isInstanceOf(NoSuchMessageException.class);*/
String message = ms.getMessage("no_content", null, "기본 메세지", null);
assertThat(message).isEqualTo("기본 메세지");
}
@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");
}
}
웹 애플리케이션에 메세지 적용해보기
다음과 같은 메시지를 설정했다고 가정했습니다.
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=취소
위와 같은 메세지가 등록되어있다고하면 타임리프에서는 메세지 표현식(#{...}) 을 사용하면 스프링의 메세지를 편리하게 조회할 수 있습니다. 예를들어 등록된 메세지 중에서 상품이라는 값을 사용하려면 ${label.item}을 사용하면 됩니다.
<div th:text="#{label.item}"> <div>
렌더링 후
<div>상품</div>
파라미터가 있는 메세지
메세지의 값이 상황에따라 변경이 되어야하는 경우가 있는데 이 경우 파라미터를 사용하면 됩니다.
메시지가 만약 hello.name = 안녕 {0} 이라고 설정되어 있다면 아래와 같이 사용하시면 됩니다.
<p th:text="#{hello.name(${item.itemName})}"></p>
만약 국제화를 통해서 언어별로 메시지를 다르게 보여주고 싶다면 아래와 같이 설정파일을 하나 더 만들면 됩니다.
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 의 값이 변경됩니다.
크롬 → 설정 → 언어에 가면 언어를 정렬해서 테스트하실 수 있습니다.
'Spring' 카테고리의 다른 글
@Transactional , Spring Data JPA 을 같이 쓰는 점에 관하여 (0) | 2025.04.08 |
---|---|
@PostConstruct , @PreDestory (0) | 2025.03.26 |
@valid vs @validated (0) | 2025.02.03 |
@Scheduled (0) | 2025.01.24 |
@Controller 와 @RestController (2) | 2025.01.22 |