💻 Frontend
Coockie를 활용하여 I18n 구현
[목차]
1) i18n1-1) i18n은 무엇인가?1-2) i18n의 활용 (feat. vue.i18n)2) 쿠키2-1) 쿠키2-2) Vue에서의 쿠키 사용3) i18n.vue 개발4) 기타4-1) hash 모드에서 한 페이지 내 특정 요소 위치로 이동(anchor)4-2) Prefetch (미리 가져오기)4-3) UTC vs GMT
1) i18n
1-1) i18n은 무엇인가?
internalization은 맨 처음의 i와 끝의 n 사이에 18개의 알파벳이 있어서 i18n이라고 부름.
i18n은 국제화라는 의미를 갖고 있다. 국제화라는 것은 특정 지역이나 언어에 종속되지 않고 다양한 지역과 언어 환경에서 정상 작동되도록 국제적으로 통용되는 소프트웨어를 설계하고 개발하는 과정을 말한다.
따라서 i18n은 단순히 번역을 제공하는 것을 넘어서 아래와 같은 사항들을 고려하며 개발하는 것을 의미합니다.
i18n 개발 시 고려사항
국제화와 지역화(L10n)

i18n은 기본적으로 리소스 정보들을 Locale에 따라 다르게 설정하고, 해당 locale 값과 매칭된 리소스 정보들을 출력하는 형태로 구현되어있다.
1-2) i18n의 활용 (feat. vue.i18n)
vue.i18n을 설치하고 vue add i18n이라는 터미널 명령어를 작성하면 기본적인 i18n을 사용하기 위한 폴더구조를 scafolding으로 만들어주지만, 직접 파일구조를 짜보자.
createI18n이라는 메서드는 i18n 모듈을 만드는 함수이고, 인자 값으로 default locale과 locale 식별이 어려울 경우 fallbackLocale을 설정할 수 있다.
또한 리소스를 객체형태로 넘길 수 있다. 리소스를 넘기는 구조는 보통 객체의 key 값으로 locale 정보를 넘기고 value는 사용되는 리소스들을 객체형태로 넘긴다.

만들어진 index 파일을 import해서 만들어진 vue 인스턴스에 use메서드의 인자로 18n 모듈을 넘겨주면 i18n 라이브러리를 사용할 수 있는 환경이 세팅된다.

그렇다면 i18n은 기본적으로 Locale 값을 기반으로 매칭된 리소스 파일을 변경한다. 그렇기 때문에 실제 컴포넌트에서 1) Locale을 변경하는 코드 2) 매칭된 Resource를 읽는 코드가 필요하다
Locale을 변경하는 코드 아래의 구현한 소스코드를 보면 셀렉트 박스가 변경될 때 마다 changSelect 함수를 호출하는데, 해당 함수는 $i18n.locale을 선택된 value값으로 바꿔주는 것이다. 즉, $i18n.locale이라는 변수가 자바스크립트에서 Locale을 인식하는 명령어임을 알 수 있다.
매칭된 Resource를 읽는 코드 매칭된 resource는 $t() 메서드로 받을 수 있다. 초기에 설정한 resource 데이터의 key값을 $t() 메서드의 인자로 넘겨주면, 해당 locale에 맞는 value값을 반환한다.
전체코드

2) 쿠키
2-1) 쿠키
쿠키는 서버가 브라우저에 보낸 데이터이다. 요청 때마다 함께 전송이 되기 때문에 보안에 취약할 수 있다.
브라우저에 저장된 쿠키는 Dom 객체를 통해서 데이터를 주고 받을 수 있다.
- 쿠키의 기본 구조
- web 브라우저의 dom 객체를 통해 데이터를 주고 받을 수 있다 (document.cookie)
- 기본적인 쿠키는 문자열을 통해 저장되고 받을 수 있다
- 쿠키 문자열의 구조는 위와 같이 3가지의 정보를 저장하게 된다.
- 쿠키정보 (”키=값”)
- 쿠키경로
- 만료일

- 데이터를 저장하는 것
- 쿠키 데이터를 저장하는 것
document.cookie = "example=hi";
document.cookie = `example2=hi2; path=/; expires=${new Date()}`;
console.log(document.cookie);
// return example=hi; example2=hi2
- 데이터를 불러오는 것
- 데이터 불러오기는 document.cookie라는 명령어를 통해서 불러올 수 있다.
2-2) Vue에서의 쿠키 사용
Vue에서 쿠키는 보통 vue-cookies라는 라이브러리를 사용한다. vue-cookies를 그 이유는 보다 쉽게 함수형태로 쿠키를 관리할 수 있기 때문이다. 라이브러리 없이도 쿠키 관리는 할 수 있지만, 라이브러리를 사용해서 관리해보자.
i18n과 같이 플러그인을 main파일에서 import하고 use명령어로 받아온다. 그러면 $cookies객체에 내장되어있는 set,get 메서드를 이용해서 함수 형태로 보다 편리하게 cookie를 사용할 수 있다.
- cookie값 저장하기
this.$cookies.set("키", "값", "만료일");
this.$cookies.set(test, "testValue");- cookie값 불러오기
const cookie = this.$cookies.get(test);
console.log(cookie); //testValue- 기타 (삭제, 쿠키있는지 확인, 모든 쿠키 가져오기, 모든 쿠키 지우기)
this.$cookies.remove("test");
//특정 쿠키가 있는지 확인
this.$cookies.isKey("test");
//모든 쿠키 키 가져오기
this.$cookies.keys().join("\n");
//모든 쿠키 다 지우기
this.$cookies.keys().forEach(cookie => this.$cookies.remove(cookie));3) i18n.vue 개발
다음과 같은 순서로 코드를 짰다.
- 선호하는 언어 select가 바뀔 때마다 cookie 값 업데이트
- 컴포넌트가 create될 때 cookie값을 가져와 locate 설정 및 text 결과값 산출
- cookie값이 없을 때는 초기값으로 웹브라우저의 선호 언어로 설정
소스코드
<template lang="">
<div>Vue.I18n</div>
<span>언어 선택 </span>
<select name="langList" v-model="selectedLang" @change="changeSelect()">
<option v-for="(item, key) in langData" v-bind:key="key" :value="item.lang">
{{ item.title }}
</option>
</select>
<br />
<span>선호하는 언어</span>
<select name="langList" v-model="favoriteLang" @change="changeFavoriteLang()">
<option v-for="(item, key) in langData" v-bind:key="key" :value="item.lang">
{{ item.title }}
</option>
</select>
<p>쿠키값: {{ this.$cookies.get("lang") }}</p>
<p>결과 : {{ $t("text") }}</p>
</template>
<script>
export default {
data() {
return {
langData: [
{ title: "Arabic", lang: "ar-SA" },
{ title: "English", lang: "en-US" },
{ title: "Russian", lang: "ru-RU" },
],
selectedLang: "ar-SA",
favoriteLang: "ar-SA",
};
},
methods: {
changeSelect() {
this.$i18n.locale = this.selectedLang;
},
changeFavoriteLang() {
this.$cookies.set("lang", `${this.favoriteLang}`);
},
},
created() {
if (this.$cookies.isKey("lang")) {
this.favoriteLang = this.$cookies.get("lang");
this.$i18n.locale = this.favoriteLang;
} else {
return;
}
},
};
</script>
<style></style>브라우저의 사용자 선호 언어 (navigator 객체) 브라우저에서 지원하는 DOM객체 중에 navigator 객체가 존재한다. 이 객체는 브라우저에서 기본적으로 갖고 있는 정보를 담고 있는 객체이다. 여러가지 메서드들 중에서 language 사용자 선호 언어를 받아올 수 있는 메서드를 통해 브라우저의 사용자 선호 언어를 값으로 받을 수 있다. 그렇다면 브라우저의 사용자 선호 언어의 값은 어떻게 만들어지는가? 이래저래 알아본 결과, OS에서 설정된 국가 및 언어를 사용한다. OS의 차이에 따라서 현재 위치를 설정 언어로 자동으로 설정하는 OS는 user의 위치에 따라서 자동으로 설정이 될 수 있는데, 결국 OS에서 설정된 국가 코드를 읽어온다. navigator.cookieEnabled (쿠키 사용가능 여부) navigator.platform (브라우저에서 인식한 컴퓨터 운영체제) navigator.language (사용자 선호 언어) navigator.languages (사용자 선호 언어리스트) etc… 실제 사용시에는 아래와 같이 cookie에서 설정된 언어를 못 읽어올 경우에는 결과값으로 브라우저 사용자 선호 언어를 읽어오게끔 했다. 이 때 기본 브라우저 Locale이 설정된 Locale이 포함되어 있지 않다면 fallbackLocale로 적용된다. <navigator.language 및 navigator.languages 설정>

4) 기타
4-1) hash 모드에서 한 페이지 내 특정 요소 위치로 이동(anchor)
- anchor란? 기존 a태그에서 href경로로 특정 #id값을 설정해서 한 페이지 내 해당 요소로 이동하는 기능
<a href="#section-2">Jump to section 2</a><br />
<h2 id="section-2">Section 2</h2>
<p>Lorem Ipsum</p>- hash, history 모드 설정
const router = createRouter({
// history: "createWebHistory", 히스토리 모드 설정
// history: createWebHashHistory(), 해쉬모드 설정
routes,
});- hash 모드로 특정 element 요소로 이동(scrollBehavior)



4-2) Prefetch (미리 가져오기)
MDN에 따르면 Prefetch는 미리 가져오기라는 뜻으로 말 그대로 사용자가
클릭할 가능성이 높은 링크의 컨텐츠를 미리 페칭해서 캐쉬보관
이후 사용자가 해당 링크를 클릭하면 페이지가 즉시 렌더링이 된다.

<link rel="prefetch" href="https://www.example.com/solutions" />비슷한 개념으로 Preload와 Preconnect 개념이 있다. 각각은 파일의 유형, 사용 빈도, 리소스의 우선순위에 따라서 변경하며 사용하는 것이 적절하다.
- preload는 현재 페이지의 먼저 가져올 리소스를 정의한다
- prefetch는 현재 페이지의 로딩이 끝나고 다음에 이동할 페이지를 가져온다
- preconnect는 미디어 파일의 커넥션을 미리 해놓는다. (조금 더 깊게 파볼 필요는 있음)
4-3) UTC vs GMT
UTC와 GMT, 그리고 Javascript의 Date객체에 대한 설명을 잘 담은 블로그 글이다.
해당 글을 요약하면
- GMT는 그리니치 표준시이고, 자바스크립트의 date 객체로 만든 것의 GMT+0900이라고 표시 되는 것은 영국시간보다 한국시간이 9시간 빠르다는 것을 뜻한다.
Mon Mar 09 2020 09:00:00 GMT+0900(한국표준시)- GMT는 그리니치 표준시가 지구의 자전속도를 기반으로 초를 정의하기 때문에 자전속도가 느려짐에 따라 초의 단위가 바뀌지만, UTC는 세슘 원자의 진동수를 기준으로 초의 정의를 새롭게 바꿨다.
- 그러나, UTC와 GMT의 시간차이는 없다고 봐도 무방하고, 특히나 자바스크립트에서는 둘을 혼용해서 사용하기 때문에 같은 단위라고 볼 수 있다. 1972년부터 UTC가 국제 표준이 되었다.
- 해당 개념을 알아야하는 것은 date값의 입력과 출력으로 UTC와 LocalTime 둘 중에 어느것으로 입출력할지를 정해야 혼동이 없다. 자바스크립트에서 해당 개념을 잘 알아야 하는 것은 Date 객체의 메서드별로 표기하는 시간대가 다르기 때문이다.



![[Browser] 리소스 우선순위 - preload, preconnect, prefetch](https://beomy.github.io/static/a061b86ded539904e8b39295bf3695a3/f635c/browser.png)
