본문 바로가기
관리자

Programming-[Backend]/Spring

[스프링 웹MVC-2] 4. 메시지, 국제화

728x90
반응형

 

 

기존 상품 등록 프로젝트를 그대로 가져온다. 강의에서 받을 수 있는 파일로 받는데, 이전 시간에 다룬 체크박스 등의 내용은 제외된다.

 

 

 

1. 개요

 

현재 프로젝트는 만약 html 상 하드코딩된 단어들을 변경해야 된다면, 일일이 찾아서 고쳐야하는 상황이다. 아래 사진에서 상품명, 가격, 수량 등을 바꿔야 한다면 직접 찾아가며 바꿔야되는 것이다.

 

이런 어려움을 해결해줄 수 있는 것이 메시지 이다. 단어들을 하드코딩하지 않고, 별도의 파일(messages.properties)에 놔두고 관리하는 것이다. 국제화 도 메시지에서 영어버전 파일은 messages_en.properties, 한글 버전 파일은 message_ko.properties로 두면 될 것이다. 그리고 HTTP의 accept-language 헤더 값을 보고 그에 맞춰서 메시지가 나가도록 하거나, 사용자의 쿠키 값에 따라서, 아니면 사용자가 선택할 수 있도록 하면 된다.

 

(예시)

item = 상품

item.id = 상품 ID

item.itemName=상품명

item.price=가격

...

 

 

 


 

 

2. 기초 세팅 및 테스트

 

 

 

스프링 메시지 소스 설정

 

원래는 스프링이 제공하는 MessageSource의 구현체인 ResourceBundleMessageSource를 빈으로 등록해야한다.

 

1
2
3
4
5
6
7
@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messagesource = new ResourceBundleMessageSource();
  messageSource.setBasenames("meesages""errors");
  messageSource.setDefaultEncoding("utf-8");
  return messageSource;
}
cs

 

basenaems 는 설정 파일의 이름을 지정하는데, 위 코드에서는 messages, errors 2개의 파일을 지정했다. messages.properties, errors.properties 파일을 읽어들이도록 설정하는 것이다. /resources/messages.properties와 같은 위치에 파일을 만들어두면 된다. 위 개요에서 살펴본대로, messages_en.properties와 같은 파일로 지정하면 국제화 처리를 할 수 있다.

 

defaultEncoding은 인코딩 정보를 저장한다. 여기서는 utf-8을 사용했다.

 


 

 

스프링 부트를 사용하면 MessageSource를 자동으로 스프링 빈으로 등록한다. 이를 위해 application.properties 안에 다음과 같은 코드를 작성해주면 된다. 

 

spring.messages.basename=messages,config.i18n.messages

 

별도로 작성하지 않으면 spring.messages.basename=messages로 messages만 읽어들이도록 기본 설정이 되어있다.

 

 

 

 

메시지 파일 작성

 

resources 폴더 아래에 일반 파일로 messages.properties라고 만들면 된다. 기본 파일이 messages.properties이고, 영어 파일은 messages_en.properties로 만들면 된다. 그러면 이 messages 파일들을 자동으로 Bundle로 묶어준다. 

 

그리고 메시지를 적용할 내용을 작성한다. 여기서 {0}은 나중에 파라미터로 받아올 배열의 인덱스를 표현하는 것이다. 테스트를 통해 이 파라미터가 어떻게 사용되는지 알아보자.

 

resources/messages.properties

 

1
2
hello=안녕
hello.name=안녕 {0}
cs

 

 

resources/messages_en.properties

 

1
2
hello=hello
hello.name=hello {0}
cs

 

 

테스트

 

테스트를 통해 기본적인 메시지 사용방법을 알아본다. 다만, 테스트 전에 인코딩 설정을 해주도록한다. File -> Settings -. File Encodings에 들어가서 아래 그림과 같이 인코딩 설정들을 UTF-8으로 변경해준다.

 

만약 설정을 바꾸었다면, 설정 변경 전 저장된 캐시를 날리기 위해 File-> Invalidate Caches...에 들어가서 캐시를 날리고 intelliJ를 재실행한다.

 

 

테스트 코드는 다음과 같다. @SpringBootTest 어노테이션을 써주면, MessageSource 클래스를 스프링부트가 알아서 찾아오기 때문에, @Autowired를 적용할 수 있다. 이렇게 되면 이전에 application.properties에서 설정해준 파일들을 찾아오게 된다.

 

application.properties

spring.messages.basename=messages,config.i18n.messages

 

getMessage의 인자는 4개이다(기본은 3개). 첫 번째는 파일 내부에 지정한 경로를 의미한다. 두 번째 인자는 {0}과 같이 지정한 배열 속의 요소로, 불러올때는 Object의 배열을 만들어서 불러와야 한다(argumentMessage 메서드 참조). 세 번째 인자는 추가로 지정할 수 있는 인자로, messages로 지정한 파일들 중에 인자로 불러오는 경로에 해당하는 파일이 없으면 NoSuchMessageException을 던지게 되는데 그때 출력할 기본 메시지를 설정한다. 마지막으로 네 번째 인자는 언어 설정에 관한 것으로 Locale을 지정하여 사용자에 따라 다른 언어가 출력되도록 할 수 있다. 뒷 부분 실습에서 살펴볼 것이다.

 

 

java/hello/itemservice/message/MessageSourceTest.java

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@SpringBootTest
public class MessageSourceTest {
 
  @Autowired
  MessageSource ms;
 
  @Test
  void helloMessage() {
    assertThat(ms.getMessage("hello"nullnull))
            .isEqualTo("안녕");
  }
 
  @Test
  void notFoundMessageCode() {
    assertThatThrownBy(() -> ms.getMessage("kkk"nullnull))
            .isInstanceOf(NoSuchMessageException.class);
  }
 
  @Test
  void notFoundMessageCodeDefaultMessage() {
    assertThat(ms.getMessage("kkk"null"기본 메시지"null))
            .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"nullnull)).isEqualTo("안녕");
    assertThat(ms.getMessage("hello"null, Locale.KOREA)).isEqualTo("안녕");
  }
 
  @Test
  void enLang() {
    assertThat(ms.getMessage("hello"null, Locale.ENGLISH)).isEqualTo("hello");
  }
}
cs

 

 

 


 

 

3. 예제에 적용해보기

 

 

만들어 놓은 프로젝트에 메시지를 적용해본다. 타임리프의 th:text=#{} 문법을 활용하면 된다. 우선 messages.properties 파일에 내용을 작성해준다. (messages_en.properties도 알맞게 작성해준다.)

 

 

resources/messages.properties

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
hello=안녕
hello.name=안녕 {0}
 
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=취소
cs

 

그리고 각 페이지 View단에서 하드코딩이 되어있던 부분에 타임리프 문법을 아래와 같이 모두 적용해주면 된다.

 

이제 서버를 실행시키면, messages.properties에 적용된대로 내용이 출력되는 것을 확인할 수 있다. 국제화를 위해서 messages_en.properties에 내용을 추가한다.

 

resources/messages_en.properties

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
hello=hello
hello.name=hello {0}
 
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
 
cs

 

그리고나서 크롬 브라우저에서는 설정 -> 고급 -> 언어 -> 화살표를 눌러서 영어를 우선순위로 두자. 그 다음 프로젝트의 웹페이지를 새로고침하면 전부 영어로 바뀌는 것을 확인할 수 있다. 이것은 View단에서 타임리프로 미리 지정해뒀기 때문이다. 이제 만약 "상품 이름"이라는 문자를 "상품명" 이라고 바꾸고 싶다면, messages.properties 파일에서 수정만 하면 전체 View에 적용될 것이다.

 

 

 

 

 

 

 


 

 

4. 추가 내용

 

 

실무에서는 'i18n -> messages -> 패키지들' 로 구성해놓고, 도메인별로 properties 파일들을 만들었다.

 

그리고 사진과 같이 CommonMessageException이 발생했을 때의 에러 메시지로 사용하거나, 또는 클라이언트로부터 전달받는 파라미터 오브젝트가 null 일때 에러를 던지는 상황에서 메시지를 활용했다.

 

 

 


 

참조

 

1. 인프런_스프링 MVC 2편 - 백엔드 웹개발 핵심 기술_김영한 님 강의

 

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2

728x90
반응형