Pinia
란?
Pinia는 Vue3 & Nuxt3에서 상태 관리 라이브러리로, Vuex와 유사한 기능을 제공합니다.
Vuex와 달리, Pinia
는 상태 관리에 Composition API
를 사용합니다.
또한, mutation, action, getter 등의 개념 없이 Store
값을 반응형으로 사용할 수 있습니다.
과거에는 Vuex가 널리 사용되었지만, Vue3에서는 Pinia가 주로 사용됩니다.
Vue Nation 2024 세션에서, Pinia 크리에이터인 Eduardo San Martin Morote
는 Pinia를 효과적으로 사용하는 방법에 대한 세션을 진행했습니다.
다음 내용은 세션에서 얻은 인사이트를 공유합니다.
1.Mutation 필요 없음
Vuex
에서는 state, mutations, actions, getters
를 통해 전역 상태를 관리할 수 있습니다.
// vuex
const store = createStore({
state: () => ({
count: 0,
isHidden: true
}),
mutations: {
increment(state) {
state.count++
},
toggle(state) {
state.isHidden = !state.isHidden
}
}
})
// getting state value in component
store.state.count
store.state.isHidden
// mutation in component
store.commit('increment')
store.commit('toggle')
Vuex에서는 상태를 변경하기 위해서는 mutation을 사용해야 했습니다.
하지만, Pinia에서는 직접 state
를 변경할 수 있습니다.
// pinia
const useToggleStore = defineStore('toggle', {
const count = ref(0)
const isHidden = ref(true)
return {
count,
isHidden
}
})
// mutaions in component
const { count, isHidden } = sotreToRefs(useToggleStore())
count.value++
isHidden.value = false
2.Pinia의 다양한 장점
Pinia는 다음과 같은 장점을 가지고 있습니다.
- Pinia는
Type safety
를 지원합니다. - Pinia는
모듈화된 Store
를 지원합니다. - Pinia는
더 나은 코드 분할
을 지원합니다. - Pinia는
Composition API
를 사용합니다.
3.타입 관리
Vuex에서는 타입 관리가 다음과 같이 스토어 외부에서 이루어졌습니다.
// wrong
cosnt state: State = {
//...
}
defineStore('...', {
state: () => state,
})
하지만, Pinia에서는 위와 같이 하지 말고, 아래와 같이 스토어 내부에서 types
를 직접 지정해야 합니다.
// correct
defineStore('...', {
state: (): State => ({
//...
})
})
4.읽기 전용 Store
Pinia에서 read-only store
를 구축하려면, 다음과 같이 코드 예제를 수정해야 합니다.
// before
const useStore = defineStore('...', {
const user = ref()
return {
// no Plugins, devtools, SSR
userReadonly: readonly(user),
// not state
get userGetter () {
return user.value
},
// not state
userComputed: computed(() => user.value)
}
})
// after
const useStore = defineStore('...', {
const user = ref()
return {
_user: user,
// valid gatter
user: computed(() => user.value)
}
})
또는, 아래와 같이 Private Store를 생성하여 관리할 수 있습니다.
이를 통해, 특정 스토어
내에서만 사용할 수 있는 변수를 생성할 수 있습니다.
const usePrivateStore = defineStore('...', {
const user = ref()
return {
user
}
})
const userStore = defineStore('...', {
const privateStore = usePrivateStore()
privateStore.user // only within the store
return {
// no user exposed
}
})
5.TypeScript
예제에서 보여드린 것처럼, 스토어에 대한 TypeScript를 작성할 때, 아래와 같이 ~ as
를 사용하는 대신, generics
를 사용하여 타입을 지정하는 것이 더 좋습니다.
// not good
const useUserStore = defineStore('user', {
const userToken = ref({} as UserToken)
const user = ref({} as User)
return {
userToken,
user
}
})
// good
const useUserStore = defineStore('user', {
const userToken = ref<UserToken | null>(null) // For initialize with null
const user = ref<User>() // For handling undefined
return {
userToken,
user
}
})
6.스크립트에서 Store 사용
아래 예제와 같이 사용하면, Pinia에서 오류가 발생합니다. Composition API를 사용할 때, setup
내에서 store
를 한 번만 호출하면 됩니다.
// wrong
<script setup>
import { useModalStore } from './store/modal'
function someMethod () {
const modalStore = useModalStore()
}
watch(something, () => {
const modalStore = useModalStore()
})
</script>
// good
<script setup>
import { useModalStore } from './store/modal'
const modalStore = useModalStore()
function someMethod () {
modalStore //
}
watch(something, () => {
modalStore //
})
</script>
이제 프로젝트를 만들어봅시다!
저는 더 많은 정보를 얻었지만, 오늘 정리한 내용은 여기까지입니다!
현재 진행 중인 Vue nation 2024
에는 훌륭한 세션들이 많이 있으며, 좋은 통찰력
을 얻을 수 있는 좋은 기회라고 생각합니다.
유익한 정보를 얻어가시길 바래요.
다음에 봐요!