7 Reusability & Composition
source: categories/study/vue-project/vue-project_7.md
7 Reusability & Composition
- 이번 챕터에서는 Vue 3.x 버전에 추가된 핵심 기능인 컴포지션(Composition) API에 대해서 자세히 알아봅니다.
- 또한 플러그인(Plugins), 믹스인(Mixins), Custom Directives 기능을 이용해서 프로젝트의 공통 모듈을 구현하고 코드를 재사용하는 방법에 대해서 익히게 됩니다.
7.1 Composition API
7.1.1 Composition API란?
- 컴포지션 API는 컴포넌트 내에서 사용하는 특정 기능을 갖는 코드를 유연하게 구성하여 사용할 수 있도록 Vue 3 버전에 추가된 함수 기반의 API입니다.
- 그동안 Vue는 ‘프로젝트 규모가 커질수록 관리하기 힘들다'는 단점이 있었습니다.
data
,computed
,watch
,methods
등 프로젝트 규모가 커질수록, 컴포넌트의 계층 구조가 복잡할수록 코드에 대한 추적 및 관리가 어려웠습니다.- 하지만 컴포지션 API를 이용하면
Setup
이라는 메소드 안에서 한 덩어리로 코드를 구현할 수 있어서 코드에 대한 관리가 훨씬 쉬워지게 됩니다. - 즉, 컴포지션 API는 그동안 Vue가 가지고 있던 단점을 보완하기 위해서 추가된 Vue3 버전의 핵심 기능입니다.
- 일반적으로 우리가 지금까지 사용했던 API는 API를 호출함으로써 API에 구현된 기능을 그대로 사용할 수 있었습니다.
- 즉, API는 특정 기능을 가지고 있고, 재사용을 위해 만들어진 것입니다.
- 컴포지션 API 역시 API라는 이름이 붙어 있는 것처럼, 특정 기능을 갖는 함수를 정의하고 API처럼 사용할 수 있게 해주는 것입니다.
- 결국 궁극적인 목적인 코드에 대한 재활용성을 높이고, 코드의 가독성을 높이기 위해 추가된 기능입니다.
- Vue 2에서는 믹스인(Mixins)을 통해 코드를 재사용하였지만, 믹스인을 사용했을 때 오버라이딩 문제나, 다중 믹스인을 사용하는 경우 코드에 대한 관리가 어려웠습니다.
- 컴포지션 API는 프로젝트에서 코드에 대한 재사용을 효율적으로 할 수 있도록 해줍니다.
- [9-1] 그림은 좀 복잡한 컴포넌트를 기존 개발 방식과 컴포지션 API로 개발했을 때의 연관성 있는 로직 단위를 색상으로 표시한 것입니다.
- 컴포지션 API로 개발하면 기존 개발 방식으로 개발했을 때보다 연관성 있는 로직을 같이 구현할 수 있어서 훨씬 코드가 간결해지고 코드 추적 및 유지 관리가 쉬워집니다.
- 동일한 프로그램 로직과 관련된 코드를 함께 배치할 수 있다면 훨씬 더 좋을 것입니다.
- 이것이 바로 컴포지션 API가 추가된 이유입니다.
7.1.2 Setup
Setup
은 컴포지션 API를 구현하는 곳입니다.
- 컴포지션 API가 어떻게 구현되는지 기존 개발 방법과 비교를 함으로써 컴포지션 API를 이해하도록 하겠습니다.
- 사용자로부터 숫자 2개를 입력받고, 입력받은 숫자를 더한 값을 출력하는 코드를 작성해 보겠습니다.
- 우리가 지금까지 배운 방법에 의하면 다음과 같은 코드로 작성될 것입니다.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="text" v-model="num1" @keyup="plusNumbers" />
<span> + </span>
<input type="text" v-model="num2" @keyup="plusNumbers" />
<span> = </span>
<span>{{ result }}</span>
</div>
</div>
</template>
<script>
export default {
name: 'calculator',
data() {
return {
num1: 0,
num2: 0,
result: 0,
}
},
methods: {
plusNumbers() {
this.result = parseInt(this.num1) + parseInt(this.num2);
}
}
}
</script>
- 사용자로부터 숫자가 입력되는 이벤트(keyup)가 발생할 때마다
plusNumbers
함수를 호출해서 사용자가 입력한 값을 더하기 해서result
로 반환하도록 코드가 작성되었습니다.
- 컴포지션 API 기능을 이용해서 동일한 기능을 갖는 코드를 작성해 보겠습니다.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="text" v-model="state.num1" @keyup="plusNumbers" />
<span> + </span>
<input type="text" v-model="state.num2" @keyup="plusNumbers" />
<span> = </span>
<span>{{ state.result }}</span>
</div>
</div>
</template>
<script>
import { reactive } from 'vue'; // reactive 추가
export default {
name: 'calculator',
setup() {
let state = reactive({ // reactive 를 이용해서 num1, num2, result 를 실시간 변경사항에 대한 반응형 적용
num1: 0,
num2: 0,
result,
})
function plusNumbers() {
state.result = parseInt(state.num1) + parseInt(state.num2);
}
return { // reactive 로 선언된 state와 plusNumbers 함수를 반환함으로써 기존 data, methods 옵션처럼 사용이 가능해짐
state,
plusNumbers,
}
}
}
</script>
- 컴포지션 API의
reactive
를 이용해서 코드를 작성했습니다. - 지금 작성된 코드는 컴포지션 API를 이용하지 않은 코드와 크게 다를 바가 없어 보입니다.
- 여기서 코드를 좀 더 수정해 보겠습니다.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="text" v-model="state.num1" />
<span> + </span>
<input type="text" v-model="state.num2" />
<span> = </span>
<span>{{ state.result }}</span>
</div>
</div>
</template>
<script>
import { reactive, computed } from 'vue'; // computed 추가
export default {
name: 'calculator',
setup() {
let state = reactive({
num1: 0,
num2: 0,
result: computed() => parseInt(state.num1) + parseInt(state.num2), // computed를 이용해서 num1, num2가 변경이 일어나면 즉시 result로 더한 값을 반환
})
return {
state,
}
}
}
</script>
reactive
와computed
를 이용하니까input type=text
에 바인딩했던keyup
이벤트를 없앨 수 있고, 코드가 훨씬 간결해졌습니다.- 지금 작성한 코드는 현재 컴포넌트 내에서만 사용 가능합니다.
- 현재 컴포넌트 내에서만 사용하는 코드를 작성하는 경우도 있지만, 계산기에서 덧셈 연산을 여러 번 반복해서 사용할 수 있는 것처럼 재사용 가능한 코드를 작성하는 경우가 있습니다.
- 이러한 경우, 작성한 코드를 여러 컴포넌트에서 재사용할 수 있도록 함수를 분리해야 합니다.
- 일단 Setup에 작성된 코드를 분리해서 별도의 function으로 작성하겠습니다.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="text" v-model="num1" />
<span> + </span>
<input type="text" v-model="num2" />
<span> = </span>
<span></span>
</div>
</div>
</template>
<script>
import { reactive, computed, toRefs } from 'vue'; // toRefs 추가
function plusCalculator() {
let state = reactive({
num1: 0,
num2: 0,
result: computed(() => parseInt(state.num1) + parseInt(state.num2))
})
return toRefs(state); // 반응형으로 선언된 num1, num2, result가 외부 function에서 정상적으로 동작하기 위해서는 toRefs를 사용해야 함
}
export default {
name: 'calculator',
setup() {
let { num1, num2, result } = plusCalculator(); // 외부 function
return {
num1,
num2,
result,
}
}
}
</script>
- 외부 function에서 반응형 변수를 사용하기 위해서
toRefs
가 추가되었습니다.
- 컴포넌트 안에서는
v-model
디렉티브를 통해 바인딩된 변수가 사용자의 입력값이 바뀔 때마다 반응형으로 처리 되었지만, - 함수를 컴포넌트 밖으로 빼면 사용자가 입력한 값에 대한 반응형 처리가 불가능해집니다.
- 그래서
toRefs
를 사용하여 컴포넌트 밖에서도 반응형 처리가 가능하도록 할 수 있습니다.
- 컴포넌트 내에서 정의된 코드를 다른 컴포넌트에서도 사용할 수 있도록 컴포넌트 밖으로 분리하겠습니다.
- common.js 파일을 생성하고 앞서 구현한 plusCaculator 코드를 다음과 같이 작성합니다.
// common.js
import { reactive, computed, toRefs } from 'vue';
const plusCalculator = () => {
let state = reactive({
num1: 0,
num2: 0,
result: computed(() => parseInt(state.num1) + parseInt(state.num2))
})
return toRefs(state);
}
export {
plusCalculator,
}
- vue 컴포넌트에서는 다음과 같이 common.js로 import해서 사용하면 됩니다.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="text" v-model="num1" />
<span> + </span>
<input type="text" v-model="num2" />
<span> = </span>
<span></span>
</div>
</div>
</template>
<script>
import { plusCalculator } from '../common.js';
export default {
name: 'calculator',
setup() {
let { num1, num2, result } = plusCalculator();
return {
num1,
num2,
result,
}
}
}
</script>
- 이렇게 특정 기능을 갖는 함수를 컴포지션 API를 이용하고 개발해서 공통 스크립트로 제공하면 뷰 컴포넌트 내에서 반응형(reactivity)으로 처리를 할 수 있어서 매우 활용도가 높아지게 됩니다.
7.1.3 Lifecycle Hooks
- 컴포지션 API 내에서 사용할 수 있는 컴포넌트 라이프사이클 훅은 다음 표와 같습니다.
Options API | Hook inside setup() |
---|---|
beforeCreate | |
created | |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
- 컴포지션 API에서 setup()은 컴포넌트 라이프사이클의 beforeCreate 와 created 훅 사이에서 실행되기 때문에,
- onBeforeCreate, onCreated 훅은 필요가 없고,
- setup() 안에서 코드를 작성하면 됩니다.
- 다음은 setup()에서 onMounted 훅을 적용한 코드입니다.
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!');
})
}
}
7.1.4 Provide / Inject
- 컴포지션 API에서 Provide / Inject 사용하려면 provide 와 inject 를 별도로 import 해야 사용할 수 있습니다.
- 부모 컴포넌트에서는 provide 함수를 통해서 전달할 값에 대한 키(key), 값(value)을 설정합니다.
<!-- CompositionAPIProvide.vue -->
<template>
<CompositionAPIInject />
</template>
<script>
import { provide } from 'vue'; // provide 추가
import CompositionAPIInject from './CompositionAPIInject';
export default {
components: {
CompositionAPIInject,
},
setup() {
provide('title', 'Vue.js 프로젝트');
// provide 함수를 통해서 전달할 키(key), 값(value) 설정
}
}
</script>
- 자식 컴포넌트에서는
inject
를 이용해서 부모 컴포넌트에서 정의한provide
키로 데이터를 가져올 수 있습니다.
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { inject } from 'vue'; // inject 추가
export default {
setup() {
const title = inject('title');
// inject를 사용해서 provide에서 정의한 키(key)로 데이터를 전달받음
return {
title,
}
}
}
</script>
7.2 믹스인(Mixins)
- 일반적인 프로그래밍 언어를 이용해서 애플리케이션을 개발할 때 우리는 공통 모듈이라고 부르는 파일을 만들게 됩니다.
- 이 파일에는 자주 사용되는 기능을 메소드로 만들어서 등록해 놓고, 개발자들은 각 화면 개발 시 공통모듈 파일을 import하고 그 기능을 사용합니다.
- Vue에서도 이렇게 공통 모듈에 해당하는 파일을 만들어서 사용할 수 있는데, 그중 하나의 방법이 믹스인입니다.
- 믹스인은 이름에서도 알 수 있듯이 믹스(mix)-인(in), 믹스인 파일을 컴포넌트 안에(in) 삽입해서, 합쳐서(mix) 사용하는 것입니다.
- 일반적인 언어의 공통모듈처럼 메소드를 정의해서 사용할 수도 있고, 이외에도 Vue의 라이프사이클 훅까지 사용할 수 있습니다.
- 이벤트 훅까지 사용할 수 있다는 것은 굉장히 큰 장점으로 작용합니다.
- 믹스인(mixin)은 기능을 따로 구현하고, 필요할 때마다 믹스인 파일을 컴포넌트에 결합해서 사용하는 방법을 말합니다.
- 예를 들어 애플리케이션 내의 모든 컴포넌트에서는 사용자가 컴포넌트에 접근할 때마다 사용자가 해당 컴포넌트에 대한 접근 권한이 있는지를 체크한다고 가정해 봅시다.
- 각각의 모든 컴포넌트에서 컴포넌트가 생성되는 시점에(beforeCreate) 사용자의 권한을 체크하는 로직을 다 넣는다고 생각하면 모든 컴포넌트에 중복된 코드가 양산되게 됩니다.
- 이런 경우 믹스인을 이용해서 사용자 권한을 체크하는 로직을 구현하고, 각각의 컴포넌트에서는 해당 믹스인 파일을 추가만 하면 됩니다.
- 믹스인은 이처럼 여러 컴포넌트에 동일한 로직을 사용할 필요가 있을 때 매우 유용합니다.
- 이러한 구조에 믹스인을 적용하면,
- 특정 기능을 캡슐화하여 단순히 코드의 수가 줄어들고 재사용성이 늘어나는 것뿐만 아니라 애플리케이션 운영 시에도 큰 이점을 가지게 됩니다.
- 사용자 권한 체크로직이 변경이 일어났을 때 믹스인 파일만 수정하면 참조하고 있는 모든 컴포넌트에 반영되기 때문입니다.
- Mock 서버의 api를 호출하는 메소드를 믹스인 파일로 만들어서 적용하겠습니다.
- 리스트 랜더링을 배울 때 Mock 서버의 api를 호출하기 위해서 axios를 통한 호출 메소드(callAPI)를 작성했습니다.
- 이렇게 서버와 통신하기 위한 코드는 대다수의 컴포넌트에서 필요한 기능입니다.
- 이러한 기능을 믹스인 파일로 만들고 서버 통신이 필요한 컴포넌트에서는 해당 믹스인 파일을 사용하면 됩니다.
- axios를 이용해서 서버 데이터를 호출했던 메소드를 믹스인으로 만들어 보겠습니다
7.2.1 믹스인(mixins) 파일 생성
- src 폴더에 api.js 파일을 생성합니다.
- 다음과 같이 axios 패키디를 이용해서 서버와의 데이터 통신을 위한 공통 함수를 작성했습니다.
// api.js
import axios from 'axios';
export default {
methods: {
async $callAPI(url, method, data) {
return (await axios({
method,
url,
data,
}).catch(e => {
console.log(e);
})).data;
}
}
}
- 함수 이름은
$callAPI
라고 작성이 되었습니다. - 함수 이름에
$
라는prefix
를 사용하는 이유는 믹스인 파일을 사용하는 컴포넌트 내에 동일한 메소드명이 있어서 오버라이딩 되는 것을 방지하기 위해서입니다.
- 일반적으로 컴포넌트에 정의되는 메소드명에는
$
와 같은prefix
를 사용하지 않기 때문에 믹스인 파일의 메소드명을 이렇게 작성하면 컴포넌트의 메소드명과 구분할 수 있습니다.
7.2.2 컴포넌트에서 믹스인(mixins) 사용
- 다음과 같이 mixins 프로퍼티에 사용할 믹스인 파일을 정의해서 사용하면 됩니다.
<!-- Mixins.vue -->
<script>
import ApiMixin from '../api.js';
export default {
mixins: [ApiMixin], // 사용할 믹스인 파일을 배열로 등록
data() {
return {
productList: [],
}
},
async mounted() {
this.productList = await this.$callAPI("https://ada1e~~~~.mock.pstmn.io/list", "get");
console.log(this.productList);
}
}
</script>
- 믹스인은 이렇게 메소드를 정의해서 컴포넌트에서 사용할 수 있게 해줍니다.
- 이외에도 믹스인은 컴포넌트에서 일어나는 이벤트 훅을 그대로 이용할 수 있다는 큰 이점을 가지고 있습니다.
7.2.3 믹스인(mixin)에서 라이프사이클 훅 이용하기
- 애플리케이션을 이용하는 사용자가 방문한 페이지 및 페이지에 머문 시간을 기록하는 코드를 작성한다고 가정합시다.
- 믹스인에 사용자가 특정 페이지에 방문하고 빠져나갈 때 데이터베이스에 시간을 저장하는 메소드를 만들었습니다.
- 각 컴포넌트에서는
mounted
훅이 발생할 때 믹스인의 방문 시작 메소드를 호출하고, unmounted
훅이 발생할 때 믹스인의 방문 종료 메소드를 호출해서- 데이터베이스에 방문 시작 시간과 방문 종료 시간을 기록하여 페이지에 머문 시간을 계산할 수 있습니다.
mounted
,unmounted
마다 모든 컴포넌트에서 믹스인에 메소드를 호출하는 것은 간편하긴 하지만,- 어찌 보면 굉장히 반복적이고 불편한 작업이 될 것입니다.
- 만약 개발자의 실수로 특정 컴포넌트에 해당 코드를 작성하지 않으면 코드가 작성되지 않은 컴포넌트의 페이지 방문 이력을 기록할 수 없게 됩니다.
- 믹스인에서는 단순히 메소드만 정의해서 사용하는 것이 아니라, 컴포넌트의 라이프사이클 훅을 그대로 이용할 수 있습니다.
- 즉, 믹스인 파일에
mounted
,unmounted
마다 데이터베이스에 방문 시작 시간과 방문 종료 시간을 기록하는 코드를 작성하면, - 해당 믹스인 파일을 사용하는 모든 컴포넌트에서는 자동으로 컴포넌트가
mounted
,unmounted
될 때 데이터베이스에 방문 기록을 저장할 수 있게됩니다.
- 실제로 믹스인 파일의
mounted
,unmounted
훅에 작성된 코드가 컴포넌트 안에서 어느 시점에 실행이 되는지 다음 코드를 통해 확인하도록 하겠습니다.
// mixins.js
export default {
mounted() {
console.log('믹스인 mounted');
},
unmounted() {
console.log('믹스인 unmounted');
}
}
<script>
import mixin from './mixin'
export default {
mixins: [mixin],
mounted() {
console.log('컴포넌트 mounted');
// 믹스인 mounted
// 컴포넌트 mounted
},
unmounted() {
console.log('컴포넌트 unmounted');
// 믹스인 unmounted
// 컴포넌트 unmounted
}
}
</script>
- 이 코드를 실행하면 컴포넌트가
mounted
되는 시점에 믹스인에 있는mounted
코드가 먼저 실행되고, - 그 다음 컴포넌트의
mounted
코드가 실행됩니다. - 즉, 컴포넌트의 라이프사이클 훅 시점에 동일한 믹스인 라이프사이클 훅 호드가 먼저 실행됩니다.
- 2개의 파일이 같은 프로퍼티, 같은 라이프사이클 훅끼리 코드가 합쳐지는데, 믹스인 코드가 먼저 실행이 됩니다.
7.2.4 믹스인 파일 전역으로 등록하기: main.js에 등록
-
api
를 호출하는 기능은 애플리케이션 내의 거의 모든 컴포넌트에서 사용하는 기능이므로 전역으로 등록해서 각 컴포넌트에서 별도의mixins
추가 없이 사용할 수 있게 하겠습니다. -
다음과 같이
mixins.js
파일을 생성합니다.
import axios from 'axios';
export default {
methods: {
async $api(url, method, data) {
return (await axios({
method,
url,
data
}).catch(e => {
console.log(e);
})).data;
}
}
}
mixins.js
파일을 전역으로 등록하기 위해서main.js
에 다음과 같이 추가합니다.
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import mixins from './mixins';
const app = createApp(App);
app.use(router);
app.mixin(mixins);
app.mount('#app');
7.3 Custom Directives
Vue
에서는v-model
,v-show
디렉티브 같은 기본 디렉티브 외에도 사용자가 직접 디렉티브를 정의해서 사용할 수 있습니다.- 웹사이트 방문 시 로그인 페이지에 접속하면 페이지가 열림과 동시에 사용자 ID를 입력하는 필드에 마우스 포커스가 위치해 있는 것을 빈번하게 보았을 것입니다.
- 사용자가 컴포넌트에 접속했을 때 지정된 입력 필드로 포커스를 위치시킬 수 있는 커스텀 디렉티브를 만들어 보겠습니다.
-
참고로 커스텀 디렉티브를 전역에서 사용할 수 있도록 등록이 가능하고, 특정 컴포넌트 안에서만 사용하도록 등록도 가능합니다.
main.js
에 커스텀 디렉티브를 다음과 같이 추가합니다.
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
})
- 코드를 보면 컴포넌트가
mounted
되면v-focus
디렉티브를 적용한HTML
객체로 포커스(el.focus()
)를 위치시키도록 작성되었습니다. - 컴포넌트에서는 다음과 같이
v-focus
디렉티브를 사용하면v-focus
디렉티브가 정의된HTML
객체에 마우스 포커스가 위치하게 됩니다.
<input type="text" v-focus />
- 실제로 지금 사용한 커스텀 디렉티브는
Vue
애플리케이셔 개발 시main.js
에 전역으로 등록해서 많이 사용합니다.
- 다음은 전역에 등록하는 방법이 아닌, 컴포넌트 내에 등록해서 사용하는 방법을 알아보겠습니다.
- 다음과 같이
directives
옵션에 정의하면 됩니다.
<script>
export default {
directives: {
focus: {
mounted(el) {
el.focus();
}
}
}
}
</script>
- 커스텀 디렉티브 사용 시에도 데이터바인딩 처리가 가능합니다.
- 다음 코드는
v-pin
디렉티브에 데이터 옵션의position
을 바인딩했습니다. - 컴포넌트가
mounted
되면v-pin
디렉티브가 지정된 HTML 객체의position
을top: 50px
,left: 100px
로 고정시킵니다.
<template>
<div style="height: 1000px">
<p v-pin="position">페이지 고정 영역 (position: fixed; top: 50px; left: 100px;)</p>
</div>
</template>
<script>
export default {
directives: {
pin: {
mounted(el, binding) {
el.style.position = 'fixed';
el.style.top = binding.value.top + 'px';
el.style.left = binding.value.left + 'px';
}
}
},
data() {
return {
position: {top: 50, left: 100}
}
}
}
</script>
- 애플리케이션에서 필요한 커스텀 디렉티브를 잘 정의해서 사용한다면 애플리케이션 개발 생산성을 향상시킬 수 있습니다.
7.4 Plugins
- 우리는 이미 플러그인이 무엇인지 잘 알고 있습니다.
- 플러그인은 특정 기능을 제공하는 코드이고, 여러분은 Vue 프로젝트를 진행할 때 유용한 플러그인들을 설치하고 사용하고 있습니다.
- NPM을 통해 설치되는 패키지 역시 플러그인입니다.
- 플러그인은 때로는 모듈로, 때로는 패키지로 사용될 수 있습니다.
- 플러그인은 특정 기능을 제공하고 쉽게 설치해서 사용할 수 있습니다.
- 아마 여러분이 프로젝트를 진행하면서 필요한 대부분의 플러그인은 이미 전 세계 개발자들 중 누군가가 개발해서 NPM에 등록했을 것이고,
- 여러분은 NPM을 통해 쉽게 설치해서 사용할 수 있습니다.
- 하지만 대규모 프로젝트를 진행하다보면 해당 프로젝트에 맞게 특화된 플러그인을 제작해야 하는 상황이 생길 수 있습니다.
- Vue에서는 직접 플러그인을 제작해서 전역으로 사용할 수 있게 해줍니다.
- 다국어(
i18n
)를 처리해주는 플러그인을 제작해 보겠습니다. src
폴더 및에plugins
폴더를 만들고 다음과 같이i18n.js
파일을 생성합니다.
// src/plugins/i18n.js
export default {
install: (app, options) => {
app.config.globalProperties.$translate = key => {
return key.split('.').reduce((o, i) => {
if (o) return o[i]
}, options)
}
app.provide('i18n', options); // i18n 키로 다국어 데이터 전달
}
}
- 플러그인은
install
옵션에서 정의해서 사용할 수 있습니다. app.config.globalProperties
를 선언하여 컴포넌트에서$translate
로 바로 접근해서 사용할 수 있습니다.
- 또한
provide
로 다국어 데이터를 전달해서 컴포넌트에서는inject
를 이용해서도 사용이 가능합니다. - 다국어 플로그인은 전역에서 사용해야 하므로
main.js
파일을 열어서 다국어 플러그인을 사용할 수 있도록 추가해야 합니다.
import i18nPlugin from './plugins/i18n'; // i18n 플러그인 추가
const i18nStrings = {
en: {
hi: 'Hello!',
},
ko: {
hi: '안녕하세요!',
}
}
const app = createApp(App);
app.use(i18nPlugin, i18nStrings); // i18n 플러그인에 다국어 번역 데이터를 파라미터로 전달
app.mount('#app');
i18nStrings
변수를 선언해서 다국어 번역이 필요한 내용을 정의한 후i18nPlugin
으로 전달합니다.
- 이제 모든 컴포넌트에서 다국어 플러그인을 사용할 수 있습니다.
- 컴포넌트에서 사용하는 방법은 다음과 같습니다.
<template>
<div>
<h2>{{ $translate("ko.hi") }}</h2> <!-- $translate로 사용 -->
<h2>{{ i18n.ko.hi }}</h2>
</div>
</template>
<script>
export default {
inject: ['i18n'], // provide로 전달된 i18n을 inject로 사용할 수 있음
mounted() {
console.log(this.i18n);
}
}
</script>