기존 프로젝트는 Vue2 위에서 Typescript를 적용하다보니 타입 정의가 매우 복잡했는데요. (참고로 vue3+vuex4 사용 시 더 편해졌다고 해요.)
예를들어 Action 별, Mutation 별, 각 타입 지정을 위해 Enum으로 함수명을 정의해야하고 또 각 타입들을 하나의 스토어로 정의하는 과정도 필요했습니다.
또한 타입 추론 덕분에 자동완성된 내용을 활용하여 접근할 수는 있지만 코드가 점점 복잡해보였습니다. (타입 추론을 활용하기 위해 Vuex Helper 함수들은 사용하지 않았었어요.)
스토어의 namespace global 모듈의 aa객체의 bb 속성에 접근
Enum으로 정의해둔 MutationType을 활용하여 Mutation 호출 (Commit)
Enum으로 정의해둔 ActionType을 활용하여 Action 호출 (Dispatch)
// 예시) app.ts
import { defineStore } from 'pinia';
// defineStore<모듈명, 타입>
export const useAppStore = defineStore('app', {
state: () => ({ drawer: false, lastName: 'test' }),
actions: {
changeDrawer() {
this.drawer = !this.drawer;
},
},
getters: {
getFullName(firstName: String) {
return firstName + lastName;
}
}
});
간단하게 useAppStore()로 store를 가져와 store 내 state에 접근하면 됩니다.
mutation이 없기 때문에 state 값을 v-model 에 사용할 때도 기존 vuex를 사용할 때와 같이 setter 를 따로 정의해주지 않아도 됩니다.
기존 vuex 코드 (v-model 사용시)
Pinia 활용 코드
<input v-model="store.drawer"/>
export default {
setup() {
const store = useAppStore();
return { store }
}
}
// 이렇게 선언할 경우 drawer는 초기값으로 계속 남아있습니다.
const { drawer } = useAppStore();
// 1. 기존과 같이 computed 활용 (값의 변경도 필요한 경우 setter도 정의 필요)
return {
count: computed(() => store.count)
}
// 2. composition API의 toRefs 활용
const { drawer } = toRefs(useAppStore());
return { drawer }
storeToRefs
Pinia 공식 문서에는 두번째 방법 (composition API의 toRefs 활용) 으로 storeToRefs를 활용하라고 나와있는데요.
현재 Vue2에서 적용이 안됩니다. 😢(#852)
Pinia의 storeToRefs 는 composition API의 toRefs와 비슷하게 동작하는데 단 Method 같은 속성은 무시하고 가져옵니다.
- Composition API - toRefs
- 리액티브 객체를 일반 객체로 변환하여 반환하지만, 반환되는 객체의 각 프로퍼티들이 ref로 원래의 리액티브 객체 프로퍼티로 연결됩니다.
<template>
<div>
fullName: {{ fullName }}
</div>
</template>
export default {
setup() {
const store = useAppStore();
return { fullName: store.getFullName }
}
}
<template>
<div>
<v-btn @click="store.changeDrawer">테스트</v-btn>
</div>
</template>
export default {
setup() {
// #1 통째로 내보내기
const store = useAppStore();
return { store }
// #2 특정 액션만 내보내기
// const store = useAppStore();
// return { changeDrawer: store.changeDrawer }
}
}
Pinia를 적용하고 기존 Vuex를 사용했을 때 보다 훨씬 사용이 간단해졌다고 느꼈습니다.
현재 Pinia 는 Vue의 공식 플러그인은 아니지만 추후 Pinia와 vuex 두 개의 프로젝트를 하나로 합치거나 쉽게 이동할 수 있도록 지원할 예정이라고 합니다.
새로운 프로젝트가 Vue2 + Typescript 환경일 때 상태 관리가 필요한 경우 Pinia 적용을 고려하셔도 좋을 것 같습니다.