회사 홈페이지를 다국어로 퍼블리싱을 해야 한다는 이야기를 듣고 나서 Spring을 이용한 다국어 페이지 만드는 방법을 여러가지 검색을 해보면서 구현을 해봤다.
나는 메세지 번들까지는 사용하지 않았다. 새로운 것을 적용하는데 오래 걸릴 것 같다는 불안감 때문에 JSTL로 분기를 나눠 JSP에서 화면상에 언어를 다르게 표현만 해주는 것으로 그쳤다. 거기까지만 했지만 알게 된 정보들이 있어 공유하려고 한다.
1. Locale을 이용해야 한다.
Locale은 사용자의 언어, 국가 뿐 아니라 사용자 인터페이스에서 사용자가 선호하는 사항을 저장하는 매개 변수의 모임이다.
출처: https://ko.wikipedia.org/wiki/%EB%A1%9C%EC%BC%80%EC%9D%BC
- Locale을 이용해서 서버에 접속하는 클라이언트에 언어를 알아낸다.
- 클라이언트에서 뽑아낸 언어를 이용하여 분기문을 거친 후 해당하는 언어권 응답 페이지를 반환하다.
이 때, 중요한 것이 클라이언트에서 보내는 request-header 안에 있는 accept-language이다.
* accept-language란?
어떤 언어를 클라이언트가 이해할 수 있는지, 그리고 지역 설정 중 어떤 것이 더 선호되는지를 알려줍니다. (여기서 언어란 프로그래밍 언어가 아니라 영어같은 자연 언어를 의미합니다.) 컨텐츠 협상을 사용하여, 서버는 제안 중 하나를 선택한 뒤, 그 것을 사용하고 Content-Language 응답 헤더와 함께 선택된 내용을 클라이언트에게 알려줍니다. 브라우저는 사용자 인터페이스 언어에 따라 해당 헤더에 적절한 값을 설정하며 사용자가 사용자 인터페이스 언어를 변경한 경우조차도, 헤더의 값이 변경되는 일은 거의 없습니다.
이 헤더는 서버가 언어를 결정할 다른 방도(명시적인 사용자 결정에 의한 구체적인 URL과 같은)를 찾지 못한 경우 사용되는 힌트입니다. 서버는 명시적인 결정을 결코 재 정의해서는 안됩니다. Accept-Language의 내용은 대게 사용자에 의해 조작되지 못 합니다.(다른 나라의 인터넷 카페를 방문하여 사용하는 경우처럼); 사용자는 그들의 사용자 인터페이스의 로케일과는 다른 언어로 된 페이지에 방문하고 싶어할 수도 있습니다.
서버가 일치되는 어떤 언어로 서브할 수 없는 경우, 이론적으로 406 (Not Acceptable) 오류 코드를 회신하게 됩니다. 그러나, 좀 더 나은 사용자 경험을 위해, 이런 경우는 드물며 그런 경우에 가장 흔한 방법은 Accept-Language 헤더를 무시하는 것입니다.
출처: https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Accept-Language
accept-language의 default값은 시스템 언어 설정을 가지고 온다.
위의 설명에서는 Header값이 변경되지 않는다고 하지만 여러 브라우저에서 request-header의 accept-language를 변경할 수 있는 것 같다.
나의 경우에는 주로 사용하는 브라우저가 크롬이기 때문에 크롬에서 accept-header의 정보를 변경해보았다.
* 크롬에서 accept-language 변경하는 방법
설정 -> 고급 -> 언어 탭을 클릭한다.
언어 추가를 눌러 추가할 언어를 선택한다.
추가한 다음에 우측 끝에 옵션키를 클릭하여 "이 언어로 Chrome 표시"를 누른 후 기존에 있던 언어는 모두 삭제한다.
나는 영어를 추가하고 영어를 선택한 다음, 한국어를 지우고 영어버전으로 다시시작을 눌렀다.
그 후 개발자 도구 network탭을 눌러 request-header의 accept-language를 확인해 보면 accept-language가 변화된 것을 확인할 수 있다.
변경된 accept-language 값을 이용하면 요청한 언어에 맞게 내가 작성한 다국어 페이지를 응답시킬 수 있다.
이제 서버 설정을 해보자.
2. Spring 프로젝트에서 설정하기
servlet-context.xml에 multipartResolver, LocaleResolver, LocaleChangeInterceptor 클래스의 빈을 등록한다.
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.commonsMultipartResolver"/>
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
<mvc:interceptors>
<beans:bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.localeChangeInterceptor">
<beans:property name="paramName" value="lang" />
</beans:bean>
</mvc:interceptors>
(참고 블로그: http://yookeun.github.io/java/2015/08/12/spring-i18n/)
SessionLocaleResolver의 경우 bean 등록시 defaultLocale을 property로 줄 수 있는데 defaultLocale을 property로 주지 않을 경우, request-header의 Accept-Language의 언어를 참고하여 Controller에서 올바른 언어권의 응답 페이지를 클라이언트에게 전송할 수 있다.
@RequestMapping(value="/", method=RequestMethod.GET)
public String home(Locale locale, Model model){
logger.info("Welcome home! The client locale is {}.", locale);
String lang = locale.getLanguage().toUpperCase();
String url;
if(lang.equals("KO")){ //한국
lang = "ko";
url = "main";
}else{ //영어권
lang = "en";
url = "foreign/en/main";
}
model.addAttribute("lang", lang);
return url;
}
HomeController에 root로 접근시 호출되는 메소드를 정의했다.
위의 메소드를 호출해서 gnb를 구현할 때는
localhost:포트번호/프로젝트명/?lang=en : 영어
localhost:포트번호/프로젝트명/?lang=ko : 한국
페이지를 응답으로 클라이언트에게 전달하면 되며, 위의 url로 접근할 경우, response-header의 content-language의 값이 변경되며 이 값이 유지되어 해당 언어권의 페이지를 응답받는다.
더 많은 내용을 보시려면 아래를 참고하세요.
블로그의 다른 글
'[개발] 프레임워크 > Spring' 카테고리의 다른 글
How to use(insert) spatial data in mysql and JPA. (0) | 2019.07.22 |
---|---|
Spring Lombok (0) | 2018.04.26 |
spring에서 디버깅 시 PolicyUtil.class can't found 뜰 때 (0) | 2018.01.14 |
maven없이 스프링(Spring) 프로젝트 만들기 (4) - Ajax 설명 (0) | 2017.11.08 |
maven없이 스프링(Spring) 프로젝트 만들기 (3) - 디비(DB, Database) 연동하기 #3 (0) | 2017.11.08 |