spring

[Spring5] 쿠키와 파라미터로 Locale 처리(CustomCookieLocaleResolver, LocaleChangeInterceptor)

moonsiri 2022. 9. 8. 12:15
728x90
반응형

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 보다 먼저 실행됩니다.

 

 

728x90
반응형