메시지
- 화면에서 사용되는 단어들을 각 화면마다 하드코딩으로 작성했다면, 수정이 필요한 경우 수정할 단어가 포함된 모든 화면을 찾아서 하나하나 수정을 해야 함
- 화면의 개수가 적으면 괜찮지만, 화면이 많으면 유지보수에 어려움이 있음
=> 메시지 : 화면에서 사용되는 다양한 단어(메시지)를 한 곳에서 관리할 수 있도록 기능
MessageSource
- 메시지 관리를 위해서 스프링에서 MessageSource를 스프링 빈으로 등록함
- MessageSource은 인터페이스고, 구현체인 ResourceBundleMessageSource를 스프링으로 등록해서 사용하면 됨
=> 스프링 부트는 자동으로 MessageSource를 스프링 빈으로 등록함
public interface MessageSource {
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
MessageSource 설정
application.properties
spring.messages.basename=messages
=> 기본값
=> /resources/아래에 messages_en.properties, messages_ko.properties, messages.properties라는 파일을 만들어두면 자동으로 인식하여 메시지 기능에 사용함
=> messages.properties을 기본 값으로 사용
messages.properties
hello=안녕
hello.name=안녕 {0}
messages_en.properties
hello=hello
hello.name=hello {0}
=> {0} 은 파라미터임
MessageSourceTest
@SpringBootTest
public class MessageSourceTest {
@Autowired
MessageSource ms;
@Test
void helloMsg() {
String resultMsg = ms.getMessage("hello", null, Locale.KOREA);
// String resultMsg = ms.getMessage("hello", null, null);
assertThat(resultMsg).isEqualTo("안녕");
}
// msg 찾지 못하면 NoSuchMessageException
@Test
void notFoundMsgCode() {
assertThatThrownBy(() -> ms.getMessage("no_code", null, null))
.isInstanceOf(NoSuchMessageException.class);
}
// 메시지가 없는 경우 기본 메시지 (기본MSG)
@Test
void notFoundMsgCodeDefaultMsg() {
String resultMsg = ms.getMessage("no_code", null, "기본MSG", null);
assertThat(resultMsg).isEqualTo("기본MSG");
}
// 파라미터 사용
@Test
void argMsg() {
String resultMsg = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(resultMsg).isEqualTo("안녕 Spring");
}
// Locale별로 메시지 가져오기
@Test
void defaultMsg() {
assertThat(ms.getMessage("hello", null, Locale.ENGLISH)).isEqualTo("hello");
assertThat(ms.getMessage("hello", null, Locale.KOREA)).isEqualTo("안녕");
}
}
=> getMessage() 메서드를 활용하여 messages.properties, messages_en.properties에서 알맞은 메시지를 불러옴
메시지 적용해보기
messages.properties
label.item=상품
label.item.id=상품 ID
label.item.itemName=상품명
label.item.price=가격
label.item.quantity=수량
label.item.open=판매여부
label.item.regions=판매지역
label.item.itemType=상품종류
label.item.deliveryCode=배송방식
page.items=상품 목록
page.item=상품 상세
page.addItem=상품 등록
page.updateItem=상품 수정
button.save=저장
button.cancel=취소
Thymeleaf로 메시지 불러오기 ( #{...} )
- 메시지 표현식인 #{...}을 사용하면 메시지를 불러올 수 있음
ex)
<h2 th:text="#{page.addItem}">상품 등록</h2>
국제화
messages_en.properties
label.item=Item
label.item.id=Item ID
label.item.itemName=Item Name
label.item.price=price
label.item.quantity=quantity
label.item.open=open
label.item.regions=region
label.item.itemType=itemType
label.item.deliveryCode=delivery
page.items=Item List
page.item=Item Detail
page.addItem=Item Add
page.updateItem=Item Update
button.save=Save
button.cancel=Cancel
=> 국제화 적용은 그냥 message_en.properties만 만들어두면 끝난 것임
Spring의 국제화 메시지 선택 방법
- Locale정보를 알아야 messages.properties을 적용할지 messages_en.properties을 적용할지 선택 가능
- Spring은 기본적으로는 LocaleResolver인터페이스의 구현체인 AcceptHeaderLocaleResolver를 활용하며, HTTP Reqeust Header의 Accept-Language보고 국제화 메시지를 선택함
- 한국어 : Accept-Language: ko,en;q=0.9,en-US;q=0.8 => messages.properties 사용
- 영어 : Accept-Language: en,ko;q=0.9,en-US;q=0.8 => messages_en.properties 사용
LocaleResolver
- Spring은 Locale선택 방식을 변경할 수 있는 인터페이스 LocaleResolver를 활용하며, 기본적으로는 Accept-Language를 활용하는 구현체 AcceptHeaderLocaleResolver를 사용함
- LocaleResolver를 구현체를 따로 만들어서 Accept-Language대신 사용자가 직접 언어를 선택하게 하고 쿠기나 세션기반(SessionLocaleResolver)으로 국제화 메시지를 선택하게 할 수도 있음
=> 인터페이스화 되어있는 스프링 장점
SessionLocaleResolver
@Bean
public SessionLocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(new Locale("ko"));
return sessionLocaleResolver;
}
사용자가 언어 선택하면 해당 사용자의 session에 설정
@RequestMapping(value = "/localeChg")
public void changeLocale(String language, HttpSession session) {
session.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale(language));
}
'WEB > spring' 카테고리의 다른 글
[Spring] Thymeleaf + Spring, 입력 <form> 다루기(체크박스) (0) | 2022.01.20 |
---|---|
[Spring] Thymeleaf 기본 기능 정리 (0) | 2022.01.16 |
[Spring] Redirect vs Forward (0) | 2022.01.02 |
[Spring] WEB-INF 디렉토리 (0) | 2022.01.02 |
[Spring] Spring Bean Scope, Provider, 프록시 (0) | 2021.12.30 |