메시지
메시지는 messages.properteis 라는 메시지 관리용 파일을 만들어
각 HTML 에 출력될 텍스트 데이터를 key 값으로 불러서 사용하는 기능입니다.
국제화
국제화는 메시지 파일( messages.properteis )을 각 나라별로 별도로 관리하면 서비스를 국제화 할 수있는 기능입니다.
예를 들어 한국에서 접속하면 화면에 출력되는 글자들이 한글로
미국에서 접속하면 화면에 출력되는 글자들이 영어로 바뀌게 하는 것입니다.
한국에서 접근한 것인지 미국에서 접근한 것인지는 인식하는 방법은
HTTP accept-language 해더 값을 사용하거나 사용자가 직접 언어를 선택하도록 하거나,
쿠키 등을 사용해서 처리할 수 있습니다.
메시지와 국제화 기능을 직접 구현할 수도 있겠지만, 스프링은 기본적인 메시지와 국제화 기능을 모두 제공합니다
그리고 템플릿 엔진인 타임리프도 스프링이 제공하는 메시지와 국제화 기능을 편리하게 통합해서 제공합니다.
먼저 메시지에 대해서 알아보겠습니다.
스프링은 기본적인 메시지 관리 기능을 제공합니다. 메시지 관리 기능을 사용하려면 스프링이 제공하는
MessageSource 를 스프링 빈으로 등록하면 되는데, MessageSource 는 인터페이스입니다.
따라서 구현체인 ResourceBundleMessageSource 를 스프링 빈으로 등록하면 됩니다.
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("messages", "errors");
messageSource.setDefaultEncoding("utf-8");
return messageSource;
}
basenames : 설정 파일의 이름을 지정합니다.
messages 로 지정하면 생성한 messages.properties 파일을 읽어서 사용합니다.
여러 파일을 한번에 지정할 수 있습니다.
여기서는 messages , errors 둘을 지정해서 errors.properties 파일도 읽어서 사용 할 수 있습니다.
추가로 국제화 기능을 적용하려면 messages_en.properties , messages_ko.properties 와 같이 파일명 마지막에
언어 정보를 주면 됩니다. 만약 찾을 수 있는 국제화 파일이 없으면 messages.properties (언어정보가 없는 파일명)를
기본으로 사용합니다. 파일의 위치는 /resources 폴더 아래 /resources/messages.properties 에 두면 됩니다.
defaultEncoding : 인코딩 정보를 지정합니다. utf-8 을 사용하면 됩니다
스프링 부트를 사용하게 된다면 스프링 부트가 MessageSource 를 자동으로 스프링 빈으로 등록하게 되므로
위의 코드를 적어줄 필요가 없습니다.
스프링 부트에서 메시지 소스 설정은 application.properties 파일에서 설정 가능합니다.
아래 코드는 기본 값으로 설정되어 있는 메시지 소스 설정입니다.
spring.messages.basename=messages
위 코드와 같이 스프링 부트에서도 메시지 설정 파일 이름을 messages로 지정합니다
따라서 messages_en.properties , messages_ko.properties , messages.properties 파일만 등록하면 자동으로 인식됩니다.
메시지 파일을 만들어 보겠습니다. 국제화 테스트를 위해 서 messages_en 파일도 추가했습니다.
/resources/messages.properties
messages.properties : 기본 값으로 사용하며 동시에 한글 국제화에도 사용합니다.
코드에서 {0} 은 파라미터를 의미합니다. 숫자 0이므로 첫 번쨰로 들어온 파라미터가 대입됩니다.
hello=안녕
hello.name=안녕 {0}
/resources/messages_en.properties
messages_en.properties : 영어 국제화에 사용합니다
hello=hello
hello.name=hello {0}
MessageSource 인터페이스 코드의 일부분입니다.
코드를 포함해 일부 파라미터를 받아 메시지를 읽어오는 기능을 제공하는 getMessage() 메서드가
오버라이딩 되어있는 것을 볼 수 있습니다
@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, "기본 메시지", null);
assertThat(result).isEqualTo("기본 메시지");
}
@Test
void argumentMessage() {
String result = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
assertThat(result).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");
}
}
테스트 코드로 메시지를 테스트 해보겠습니다
첫 번쨰 테스트 메서드에서는 code 에만 hello 만 넣어주고
메시지 파라미터인 args 와 지역 정보 locale 은 null 값을 입력했습니다.
locale 값이 없으면 basename 에서 설정한 기본 이름 메시지 파일을 조회하게 됩니다.
여기서는 basename을 messages로 지정했으니 messages.properties 파일에서 조회하여 값을 꺼내옵니다.
두 번째 테스트 메서드에서 code 에만 값을 넣어줬는데 messages.properties 파일에 없는 키 값을 적어주었습니다.
이 때는 NoSuchMessageException 예외가 발생하게 됩니다.
하지만 세 번째 테스트 메서드처럼 기본값을 지정해준다면 code 파라미터에 넣어준 키 값이 존재하지 않아도
예외가 발생시키지 않고 기본값을 반환해줍니다.
네 번째 테스트 메서드에서는 code 에 파라미터가 있는 메시지의 키 값을 넣어주고 메시지의 파라미터도 넣어줘
안녕에 파라미터로 들어온 값 Spring 을 뒤에 붙인 결과를 반환해줍니다.
다섯 번째 테스트 메서드 지역 정보인 locale 에 값을 넣어봤습니다.
여기서는 따로 messages_ko.properties 파일을 생성하지 않아 지역 정보인 locale 값이 Korea 면
찾을 수 없는 국제화 파일로 인식해 messages.properties 에서 키 값에 대한 데이터를 결과로 반환합니다.
그러므로 locale 값 null 이든 korea 이든 결과가 같습니다.
마지막 테스트에서는 locale 값을 English 로 주어 messages_en.properties 파일에서 값을 가져옵니다
이번에는 웹 어플리케이션에 메시지를 적용해보겠습니다.
@Controller
public class TestController {
@GetMapping("/test")
public String items(Model model) {
return "/message/test";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="#{hello}">메시지 국제화 테스트</h1>
<h1 th:text="#{hello.name(Spring)}">메시지 국제화 테스트</h1>
</body>
</html>
웹 어플리케이션에서도 타임리프를 사용해서 잘 적용되는걸 확인 할 수 있었습니다.
이번에는 언어 설정 값을 영어로 바꿔 국제화를 적용시켜보겠습니다.
웹 브라우저 Chrome(크롬) 에서 설정을 들아가서 언어를 검색한 후 영어를 가장 위로 이동으로 해줍니다.
그리고 새로고침을 해서 같은 페이지를 보면
국제화도 잘 적용되는걸 확인 할 수 있습니다.
웹 브라우저의 언어 설정 값을 변경하면 요청시 Accept-Language 의 값이 변경되기 때문에
이렇게 국제화가 적용 될 수 있씁니다
Accept-Language 는 클라이언트가 서버에 기대하는 언어 정보를 담아서 요청하는 HTTP 요청 헤더입니다.
앞에서 서 MessageSource 테스트에서 볼 수 있었듯이 메시지 기능은 Locale 정보를 알아야 언어를 선택할 수 있습니다.
스프링은 Locale 정보를 알아야 언어를 선택할 수 있고,
스프링은 언어 선택시 기본으로 AcceptLanguage 헤더의 값을 사용합니다.
스프링은 Locale 선택 방식을 변경할 수 있도록 LocaleResolver 라는 인터페이스를 제공하는데,
스프링 부트는 기본으로 Accept-Language 를 활용하는 AcceptHeaderLocaleResolver 를 사용합니다.
그래서 현재 웹 브라우저의 언어 설정 값을 변경하고 요청시 Accept-Language 의 값이 변경되었던 것입니다.
만약 Locale 선택 방식을 변경하려면 LocaleResolver 의 구현체를 변경해서 쿠키나 세션 기반의 Locale 선택 기능을
사용할 수 있습니다. 예를 들어서 클라이언트가 직접 Locale 을 선택하도록 하는 것입니다.
'Spring' 카테고리의 다른 글
[Spring] AOP(Aspect Oriented Programming) 개념 이해하기 (0) | 2022.10.13 |
---|---|
[Spring] 필터(Filter) 인터셉터(Interceptor) (0) | 2022.10.11 |
[Spring] 빈 생명주기 콜백(Bean Lifecycle Callback) (0) | 2022.09.05 |
[Spring] 스프링 MVC 구조 (0) | 2022.09.04 |
[Spring] @RequestBody @ResponseBody HTTP message body 데이터 송수신 (0) | 2022.08.31 |
댓글