개발자로 후회없는 삶 살기

spring PART.메시지, 국제화 본문

[백엔드]/[spring | 학습기록]

spring PART.메시지, 국제화

몽이장쥰 2023. 4. 19. 23:52

서론

※ 이 포스트는 다음 강의의 학습이 목표임을 밝힙니다.

https://www.inflearn.com/roadmaps/373

 

우아한형제들 최연소 기술이사 김영한의 스프링 완전 정복 - 인프런 | 로드맵

Spring, MVC 스킬을 학습할 수 있는 개발 · 프로그래밍 로드맵을 인프런에서 만나보세요.

www.inflearn.com

 

본론

- 메시지

화면의 상품명을 모두 상품이름으로 바꾸고 싶습니다. 이 프로젝트는 5군데가 하드코딩 되어있는데 실무에서는 수 백개를 고쳐야 할 수도 있습니다. 이때 여러 화면을 다 찾아가면서 고치는게 불편합니다. 이런 다양한 메시지를 한 곳에 관리하도록 하는 기능을 메시지 기능이라고 합니다.

messages.properties라는 메시지 관리용 파일을 만들고 위 사진처럼 키, 벨류로 파일을 채워놓고 각 html들이 위 데이터의 키로 값을 불러다 쓰는 것입니다. 그러면 이 파일만 고치면 전체 파일이 적용이 됩니다. 이렇게 하드코딩된 것을 파일로 관리하는 것을 메세지로 관리한다고 합니다.

 

 

- 국제화

한국에서 들어가면 한국어로 보이고 미국에서 들어가면 미국어로 보이는 국제화 사이트를 만들고 싶습니다. 이것은 메세지에 properties 파일을 각 나라별로 별도로 관리를 하면 됩니다. message_en, message_ko로 파일을 각각 만들어서 HTTP 헤더에 accept-language가 영어면 _en에서 불러다 쓰는 것입니다.

 

> 또 다른 방법으로는 사용자가 직접 언어를 선택하도록 하고 그 선택된 것을 쿠키에 녹여놓으면 그 사용자는 요청할 때마다 쿠키에서 값을 가져다가 웹 사이트에 알려주기 때문에 한국어를 선택했으면 _ko 파일에서 가져다 쓰도록 개발자가 구현할 수 있습니다.

 

> 스프링은 '기본'적으로 메시지와 국제화 기능을 타임리프와 통합해서 모두 제공합니다.

 

- 스프링 메시지 소스 설정

메세지 관리 기능을 사용하려면 MessageSource를 스프링 빈으로 등록해야합니다. 이것을 스프링이 자동으로 등록해줍니다. setBasenames에 이름을 주면 message.properites 파일을 읽어서 사용합니다.

 

위를 보면 message.properites와 errors.properties 두개를 읽는 것입니다. > 파일의 위치는 resourses 밑에 두면 됩니다. 스프링이 이 파일을 자동으로 읽어서 메시지와 국제화를 지원해줍니다. 

 

프로퍼티스에 설정을 하면 resourses 밑에 messages, resources/config/i18n/messages 파일을 넣고 부릅니다. messages를 지정해두면 messages_en, _ko를 다 읽습니다.

 

-> 메세지 파일 만들기

리소스에 messages.properties 파일을 만듭니다. 그 안에 키, 벨류 형식으로 데이터를 넣습니다. {0}는 메시지를 부를 때 파라미터를 넣는 것입니다.

 

한국에서 들어오면 default인 messages를 쓰고 미국에서 들오면 en을 씁니다. 영어가 아니면 다 한국을 씁니다. 이제 설정을 다 끝났고 실제 스프링에서 스프링 빈에 등록된 메세지를 불러다 쓰는지 알아보겠습니다.

 

- 메세지 소스 사용

@SpringBootTest
public class MessageSourceTest {

    @Autowired
    MessageSource ms;

    @Test
    void helloMessage() {
        String hello = ms.getMessage("hello", null, null);
        assertThat(hello).isEqualTo("안녕");
    }
}

스프링 빈에 등록된 게 메세지 소스입니다. 이제 이 빈을 가져다 쓰면 이 안에 위에서 등록한 메세지 파일을 가지고 있는 것입니다. 

> 메시지 소스는 getMassage로 메세지를 부릅니다. 패키지를 만들고 테스트해보자 @SpringBootTest를 붙이고 @Autowired로 메세지 소스를 주입받습니다. 그러면 기본으로 아까 만든 messages.properties를 불러들입니다. 불러들이는 것은 아까 application.properties에 썼기 때문입니다. 

> 잘 돌아가나 보겠습니다. ms.getMessage()하고 3가지 인자가 있습니다. 코드, args, locale로 돌려보면 hello를 넘기고 locale이 null이라 기본인 message.properties가 선택이 됩니다.

 

-> 기본 메세지

@Test
void notFoundMessageCode() {
    assertThatThrownBy(() -> ms.getMessage("no code", null, null))
            .isInstanceOf(NoSuchMessageException.class);
}

메세지 코드를 찾을 수 없는 경우는 예외가 발생합니다. no code는 messages.properties에 없기에 예외가 발생할 것입니다. NoSuchMessageException이 발생합니다.

@Test
void notFoundMessageCodeDefualtMessage() {
    assertThatThrownBy(() -> ms.getMessage("no code", null, "기본메시지", null))
            .isInstanceOf(NoSuchMessageException.class);
}

> 기본 메세지를 줄 수 있는데 메시지를 못찾으면 기본 메시지를 그냥 줍니다.

 

-> args 주기

@Test
void argsMessage() {
    String message = ms.getMessage("hello.name", new Object[]{"Spring"}, null);
    assertThat(message).isEqualTo("안녕 Spring");

}

매개변수를 주면 값을 넘겨서 값을 치환을 합니다. 넘길 때 obj 배열을 넘겨야합니다. spring으로 치환이 됩니다.

 

-> 국제화

@Test
void enMessage() {
    String message = ms.getMessage("hello", null, Locale.ENGLISH);
    assertThat(message).isEqualTo("hello");
}

Locale을 Korea를 주면 기본 값을 준 것과 같습니다. 왜냐면 messages.properties가 기본인데 거기에 한국어가 있습니다. locale을 eng로 주면 국제화가 됩니다.

 

- 웹 어플리케이션에 메시지 적용

상품 관련 메세지를 키, 벨류에 넣어둡니다. 타임리프에는 #으로 메시지 표현식으로 스프링이 편리하게 메시지를 조회할 수 있습니다. 메세지에 상품 value를 쓰려면 #{label.item}을 쓰면 됩니다. 메세지는 $가 아니라 #을 쓴다는 것입니다. 그러면 렌더링할 때 파일을 읽어다가 바꿔줍니다.

 

상품 목록부터 바꿔보자 th:text로 태그의 content에 값을 넣어주면 됩니다.

메세지와 국제화가 들어가야하는 태그에 전부다 #을 하면 됩니다. 파라미터는 <p th:text="#{hello.name(${item.itemName})}"></p> 이렇게 #하고 ()안에 넣어주면 됩니다.

 

- 웹 어플리케이션에 국제화 적용

영어로 싹 바꿔보자 영어 메세지를 추가합니다. 이러면 작업이 끝납니다. 왜냐하면  이미 앞에서 템플릿에 #을 넣어서 메세지를 사용하게 해놨습니다. 그러니 이미 템플릿에는 한국어도 되고 영어도 되는 것입니다. 이제 locale만 선택하면 됩니다.

 

> 크롬에서 설정하면 됩니다. 브라우저의 요청 헤더가 accept lang이 영어로 바뀌어서 locale이 영어로 되어서 _en 메세지 파일이 선택되는 것입니다.

Comments