[Spring5] 쿠키와 파라미터로 Locale 처리(CustomCookieLocaleResolver, LocaleChangeInterceptor)
Cookie를 이용하여 Locale을 정의하는 CookieLocaleResolver과 언어 파라미터에 따라 Locale을 변경해주는 LocaleChangeInterceptor에 대해 포스팅하겠습니다.
CookieLocaleResolver
CookieLocaleResolver는 말 그대로 Cookie를 이용해서 Locale 정보를 담는 것입니다. setLocale()을 통해 Locale 정보를 담은 Cookie를 생성하고 resolverLocale()에서 Cookie로 부터 Locale 정보를 가지고 옵니다.
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setLanguageTagCompliant(false);
localeResolver.setDefaultLocale(Locale.US);
localeResolver.setCookieName(LANG_PARAM_COOKIE_NM);
localeResolver.setCookieMaxAge(COOKIE_MAX_AGE);
localeResolver.setCookieDomain(COOKIE_DOMAIN);
return localeResolver;
}
Property | default | 설명 |
cookieName | classname + locale | 쿠키명 |
cookieMaxAge | integer.MAX_INT | 쿠키 유효 시간, 01로 해두면 브라우저를 닫을 때 없어짐 |
cookiepath | / | Path를 지정하면 해당하는 Path와 그 하위 Path 에서만 참조 |
cookieDomain | 도메인 | 쿠키 도메인 |
cookieSecure | false | 쿠키 보안 여부 |
defaultLocale | Locale이 설정되지 않았을 경우 기본값 |
defaultLocale을 CloudFront Country의 Locale로 설정
defaultLocale을 설정하면 Locale이 설정되지 않았을 경우 defaultLocale로 locale이 정의되는데,
사용자가 접속하는 국가에 따라 Locale을 설정할 수 있게 고정값이 아닌 aws CloudFront에서 조회해오는 country값으로 Locale을 설정해보겠습니다.
그러기 위해선 CookieLocaleResolver에서 defaultLocale이 어떻게 설정되는지 확인할 필요가 있습니다.
CookieLocaleResolver의 resolveLocaleContext 메서드에서, 정확히는 determineDefaultLocale 메서드에서 defaultLocale을 설정합니다.
@Nullable
protected Locale determineDefaultLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale == null) {
defaultLocale = request.getLocale();
}
return defaultLocale;
}
CookieLocaleResolver를 상속받아 해당 메서드를 커스텀하겠습니다.
public class CustomCookieLocaleResolver extends CookieLocaleResolver {
/** AWS CF를 거친 후 존재하는 국가코드의 헤더키 명 */
private static final String CF_HEADER_COUNTRY_NAME = "CloudFront-Viewer-Country";
@Override
protected Locale determineDefaultLocale(HttpServletRequest request) {
String countryByCloudFront = request.getHeader(CF_HEADER_COUNTRY_NAME);
if (countryByCloudFront != null) {
// country코드 값으로 페이지에서 제공하는 locale 조회
return LangCultureCd.getCountryToLangCulture(countryByCloudFront).getLocale();
}
return super.determineDefaultLocale(request);
}
}
그리고서 Configuration에서 CookieLocaleResolver를 CustomCookieLocaleResolver로 교체합니다.
@Bean
public LocaleResolver localeResolver() {
CustomCookieLocaleResolver localeResolver = new CustomCookieLocaleResolver();
localeResolver.setLanguageTagCompliant(false);
localeResolver.setDefaultLocale(Locale.US);
localeResolver.setCookieName(LANG_PARAM_COOKIE_NM);
localeResolver.setCookieMaxAge(COOKIE_MAX_AGE);
localeResolver.setCookieDomain(COOKIE_DOMAIN);
return localeResolver;
}
+)
참고로 Spring6에서는 determineDefaultLocale 메서드가 deprecated 처리되었습니다.
아래와같이 설정할 수 있습니다.
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setLanguageTagCompliant(false);
localeResolver.setDefaultLocale(Locale.US);
localeResolver.setCookieName(LANG_PARAM_COOKIE_NM);
localeResolver.setCookieMaxAge(COOKIE_MAX_AGE);
localeResolver.setCookieDomain(COOKIE_DOMAIN);
localeResolver.setDefaultLocaleFunction(request -> {
String countryByCloudFront = request.getHeader(CF_HEADER_COUNTRY_NAME);
if (countryByCloudFront != null) {
// country코드 값으로 페이지에서 제공하는 locale 조회
return LangCultureCd.getCountryToLangCulture(countryByCloudFront).getLocale();
}
return super.determineDefaultLocale(request);
});
return localeResolver;
}
setLocale()
아래에서 다룰 LocaleChangeInterceptor에서 사용되는 로직으로 locale 값을 받아 Cookie에 담을 수 있습니다.
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale newLocale) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
localeResolver.setLocale(request, response, StringUtils.parseLocale(newLocale));
}
getLocale()
LocaleContextHolder에서 locale을 가져옵니다. (null 일 수 없음, 값이 없으면 defaultLocale에서 가져옴)
public Locale getLocale(HttpServletRequest request) {
return LocaleContextHolder.getLocale();
}
LocaleChangeInterceptor
LocaleChangeInterceptor는 파라미터로 locale이 전달 되면 해당 locale로 LocaleResolver에 setLocale해줍니다.
LocaleResolver bean 설정이 되어있어야합니다.
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@Bean
public LocaleChangeInterceptor localeInterceptor() {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName(LANG_PARAM_NM);
interceptor.setIgnoreInvalidLocale(true);
return interceptor;
}
Property | default | 설명 |
paramName | locale | 파라미터명 |
ignoreInvalidLocale | false | 유효하지 않은 locale인 경우 오류 발생 여부 |
Configuration에서 설정한 파라미터 명으로 값을 전달하면 LocaleChangeInterceptor의 preHandle에서 Cookie에 locale을 저장합니다.
- https://moonsiri.tistory.com/?locale=ko
참고로 LocaleChangeInterceptor는 Interceptor 보다 먼저 실행됩니다.