Pinia 는 Vue의 새로운 상태 관리 라이브러리입니다.
Pinia 는 2019년 11월경 Composition API 를 사용하여 Store for Vue가 어떻게 생겼는지 재설계하기 위한 실험으로 시작되었습니다.
그 이후 초기 원칙은 동일하지만 Pinia 는 Vue2와 Vue3 모두에서 작동하며 Composition API 를 사용할 필요는 없습니다.
- VueConf Toronton 2021 에서 Vue의 창시자 Evan You가 상태 관리 플러그인으로 vuex가 아닌 Pinia를 추천
Pinia([piːnjʌ] 영어로 "peenya" 로 발음됨) 는 유효한 패키지 이름인 piña(스페인어로 파인애플) 에 가장 가까운 단어입니다.
파인애플은 실제로 여러개의 과일을 만들기 위해 결합된 개별 꽃의 그룹입니다. Store 와 마찬가지로 하나하나가 개별적으로 태어나지만 격국에는 모두 연결되어 있음을 의미합니다.
Pinia를 사용해야 하는 이유?
Pinia 는 Vue의 구성 요소/페이지 간에 상태를 공유할 수 있습니다.
Composition API 에 익숙하다면 아래와 같은 형태의 간단한 내보내기로 전역 상태를 공유 할수 있다고 생각 할 수 있습니다.
export const state = reative({})
이는 단일 페이지 애플리케이션에 해당하지만 서버 측에서 랜더링 되는 경우 애플리케이션을 보안 취약성에 노출 시킵니다.
그러나 작은 단일 페이지 어플리케이션에서도 Pinia 를 사용하면 많은 것을 얻을 수 있습니다.
Mutations 이 없습니다.
- 상태변경을 위해 mutations 를 정의하고 commit 하는 과정이 필요없습니다.
- vue 인스턴스의 state 값을 변경 할 때 처름 read/write 하면됩니다.
Typescipt 를 지원
- Typescipt 를 통한 유형 추론을 최대한 활용할 수 있게 만들어져 있어서 복잡한 래핑을 하지 않아도 된다.
- 타입을 별도로 지정해주지 않아도 타입 추론이 가능하다.
Namespace modules 없음
Devtools 지원
서버 측 렌더링 지원
Pinia 와 Vuex의 다른점
Pinia 의 Store 선언 구문
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
})
Vuex 와의 가장 큰 차이점이라고 할 수 있는 것은 mutations 의 유무이다.
Vuex 에 존재하던 mutations 선언 필요 없이 actions 에서 값을 변화 시킬 수 있게 되었다.
사용할 때는 아래와 같은 형태로 사용한다.
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
const onClickAdd = () => {
// actions 를 직접선언
counter.increment()
// 이런식으로 Composition API 사용하는식으로 사용도 가능
counter.count++
// 내부 API 를 사용 가능하고 (with autocompletion ✨)
counter.$patch({ count: counter.count + 1 })
}
return {
onClickAdd,
doubleValue: computed(() => counter.doubleCount),
}
}
}
위와 같이 Composition API 에서 사용형태와 비슷하며 쉽고 간편하게 Store 에 접근이 가능하다.
기존에 Vuex 에서 Store 정의하고 mutation , actions , getters 순서대로 작성하고 dispatch 를 이용하여 개발하던 것보다 훨씬 간편해졌다.
만약 computed 선언을 하지 않고 구조분해할당을 하고 싶다면
// App.vue
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
export default {
setup() {
const counter = useCounterStore()
const { doubleCount } = storeToRefs(counter)
const onClickAdd = () => {
counter.count++
}
return {
onClickAdd,
doubleCount
}
}
}
위와 같이 하면 쉽고 간편하게 사용할 수 있다.
Vue3의 반응형 시스템 내부에서 구조분해할당을 사용하는 경우 반응형이 작동하지 않기 때문에 Vue3 에서 구조분해할당을 사용하시 위해 반응형 객체를 toRefs 로 묶어서 반응형을 유지할 수 있도록 지원한다.
참조
Composition API 에 익숙 하다면 아래와 같은 형태로 사용할 수도 있다.
// stores/counter.js
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
const doubleCount = computed(() => count.value * 2)
return { count, increment, doubleCount }
})
마치며
기존 상태관리 라이브러리인 vuex 와 비교를 해보았을때 Pinia 가 매력적인 몇가지 사항들이 있는데, mutations 가 없어진 것과 Typescript 지원 그리고 devtools 의 공식 지원이다. 이번 새로운 프로젝트에 Pinia 도입 해서 사용해 보았는데 Composition API, Typescript 과의 궁합도 잘맞았다.
Vuex 와 동시 사용도 가능 하다고 하니 다들 한번 사용해 보시면 좋을것 같습니다.
참조
피니아 공식문서
Pinia - Vuex 를 대체할 새로운 Store!
Pinia
Pinia vs. Vuex: Which state management library is best for Vue?