메시지, 국제화 소개
1. 메세지
• 상품명이라는 단어를 모두 상품이름으로 고쳐야할 경우 여러 화면에 있는 상품명을 찾아가면서 수동으로 모두 변경해야 함
• HTML 파일에 메시지가 하드코딩 되어 있기 때문인데 이런 다양한 메시지를 한 곳에서 관리하도록 하는 기능을 메시지 기능이라 함.
• 적용 방법
- messages.properties메시지 관리용 파일 생성 후 해당 데이터를 key 값으로 불러서 사용
ex) messages.properties메시지
item=상품 item.id=상품 ID item.itemName=상품명 item.price=가격 item.quantity=수량 |
ex) 적용
addForm.html |
editForm.html <label for="itemName" th:text="#{item.itemName}"></label> |
2. 국제화
• 메시지에서 설명한 메시지 파일(messages.properties)을 각 나라별로 별도로 관리하면 서비스를 국제화 할 수 있음
ex) messages_en.properties메시지
item=Item item.id=Item ID item.itemName=Item Name item.price=price item.quantity=quantity |
ex) messages_ko.properties메시지
item=상품 item.id=상품 ID item.itemName=상품명 item.price=가격 item.quantity=수량 |
• 영어를 사용하는 사람이면 messages_en.properties를 사용하고, 한국어를 사용하는 사람이면 messages_ko.properties를 사용하게 개발하면 사이트를 국제화 할 수 있음
• 한국어로 표현할지 영어에 표현할지 판단하는 방법은 HTTP accept-language 해더 값을 사용하거나 사용자가 직접 언어를 선택하도록 하고, 쿠키 등을 사용해서 처리하면 됨
• 메시지와 국제화 기능을 직접 구현할 수도 있겠지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공함.
• 타임리프도 스프링이 제공하는 메시지와 국제화 기능을 편리하게 통합해서 제공함
스프링 메시지 소스 설정
1. 메세지 관리 빈 직접 등록
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages", "errors");
messageSource.setDefaultEncoding("utf-8");
return messageSource;
}
• MessageSource를 스프링 빈으로 등록하면 되는데, MessageSource는 인터페이스임
• 따라서 구현체인 ResourceBundleMessageSource를 스프링 빈으로 등록하면 됨.
• messageSource.setBasenames("messages", "errors")
- basenames : 설정 파일의 이름을 지정
- 여러 파일을 한번에 지정 가능(messages , errors)
- messages로 지정하면 messages.properties 파일을 읽어서 사용
-
추가로 국제화 기능을 적용하려면 messages_en.properties , messages_ko.properties와 같이 파일명 마지막에 언어 정보를 주면됨
- 만약 찾을 수 있는 국제화 파일이 없으면 messages.properties (언어정보가 없는 파일명)를 기본으로 사용.
- 파일의 위치는 /resources/messages.properties에 두면 됨.
• defaultEncoding : 인코딩 정보 지정 utf-8 사용
2. 스프링 부트 메세지 소스 설정
2.1 MessageSource 설정
• 스프링 부트를 사용하면 스프링 부트가 application.properties를 읽어 MessageSource를 자동으로 스프링 빈으로 등록
2.2 application.properties 설정
• spring.messages.basename=messages,errors
- 위의 basenames설정과 같음
※ 스프링 부트 메시지 소스 기본 값
- spring.messages.basename=messages
※ MessageSource를 스프링 빈으로 등록하지 않고, 스프링 부트와 관련된 별도의 설정을 하지 않으면 messages 라는 이름으로 기본 등록
※ messages_en.properties , messages_ko.properties , messages.properties 파일만 등록하면 자동으로 인식.
3. 메세지 파일 만들기
• /resources/messages.properties 파일 생성
hello=안녕 hello.name=안녕 {0} |
• /resources/messages_en.properties 파일 생성
hello=hello hello.name=hello {0} |
스프링 메세지 소스 사용
1. 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;
• 코드를 포함한 일부 파라미터로 메시지를 읽어오는 기능을 제공
2. 등록한 메세지 프로퍼티스 테스트 소스
2.1 단순한 메세지 조회 테스트 소스
@Test
void helloMessage() {
String result = ms.getMessage("hello", null, null);
assertThat(result).isEqualTo("안녕");
}
• ms.getMessage("hello", null, null)
- code: hello
- args: null
- locale: null
• locale 정보가 없으면 Locale.getDefault()을 호출해서 시스템의 기본 로케일을 사용하여 메시지 파일을 조회
• locale 정보에 맞는 messages_xx.properties가 없다면 기본 messages.properties조회
• application.properties에서 basename으로 messages를 지정 했으므로 messages.properties 파일에서 데이터 조회
2.2 메시지가 없는 경우, 기본 메세지 테스트 소스
@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 )를 사용하면 기본 메시지가 반환됨
2.3 매개변수를 사용 하는 메세지 테스트 소드
@Test
void argumentMessage() {
String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(result).isEqualTo("안녕 Spring");
}
• hello.name=안녕 {0} → Spring 단어를 매개변수로 전달 → 안녕 Spring
3. 국제화 파일 선택
3.1 국제화 파일 선택 하는 메세지 테스트 소스 1
@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 를 사용
3.2 국제화 파일 선택 하는 메세지 테스트 소스 2
@Test
void enLang() {
assertThat(ms.getMessage("hello", null,
Locale.ENGLISH)).isEqualTo("hello");
}
• ms.getMessage("hello", null, Locale.ENGLISH) : locale 정보가 Locale.ENGLISH이므로 messages_en을 찾아서 사용
웹 애플리케이션에 메세지 적용하기
1. 메세지 등록
• 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=취소 |
2. 타임리프에 메세지 적용
※ 타임리프의 메세지 표현식 : #{ ... }
2.1 페이지 이름에 적용
<h2 th:text="#{page.addItem}">상품 등록</h2>
2.2 레이블에 적용
<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
<label for="price" th:text="#{label.item.price}">가격</label>
<label for="quantity" th:text="#{label.item.quantity}">수량</label>
2.3 버튼에 적용
<button type="submit" th:text="#{button.save}">저장</button>
<button type="button" th:text="#{button.cancel}">취소</button>
2.4 파라미터에 사용하는 방법
<p th:text="#{hello.name(${item.itemName})}"></p>
웹 어플리케이션에 국제화 적용하기
1. 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 |
2. 웹으로 확인하기
• 웹 브라우저의 언어 설정 값을 변경하면서 국제화 적용을 확인가능
• 크롬 브라우저 설정 언어를 검색하고, 우선 순위를 변경하면 됨
• 웹 브라우저의 언어 설정 값을 변경하면 요청시 Accept-Language 의 값이 변경
• Accept-Language 는 클라이언트가 서버에 기대하는 언어 정보를 담아서 요청하는 HTTP 요청 헤더임
3. 스프링의 국제화 메시지 선택
• 메시지 기능은 Locale 정보를 알아야 언어를 선택할 수 있음
• 스프링도 Locale 정보를 알아야 언어를 선택할 수 있는데, 스프링은 언어 선택시 기본으로 Accept-Language 헤더의 값을 사용함.
4. LocaleResolver
• 스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver라는 인터페이스를 제공함.
• 스프링 부트는 기본으로 Accept-Language를 활용하는 AcceptHeaderLocaleResolver를 사용
• LocaleResolver 인터페이스
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request);
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}
• LocaleResolver 변경
- Locale 선택 방식을 변경하려면 LocaleResolver의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택 기능을 사용할 수 있음
- 고객이 직접 Locale을 선택하도록 변경가능
'일상의 흔적 > Study' 카테고리의 다른 글
인프런 스프링 MVC 2 (백엔드 웹개발 활용 기술) : Bean validation - 5 (0) | 2023.03.19 |
---|---|
인프런 스프링 MVC 2 (백엔드 웹개발 활용 기술) : validation - 4 (0) | 2023.03.19 |
인프런 스프링 MVC 2 (백엔드 웹개발 활용 기술) : Thyemleaf 스프링통합과 폼 - 2 (0) | 2023.03.19 |
인프런 스프링 MVC 2 (백엔드 웹개발 활용 기술) : Thyemleaf 기본기능 - 1 (0) | 2023.03.18 |
인프런 스프링 MVC 1 (웹개발 핵심 기술) : 스프링 MVC 웹페이지 만들기 - 7 (0) | 2023.03.18 |