원문 : https://medium.com/vue-mastery/advantages-of-pinia-vs-vuex-44e759133fed
David Nwadiogbu 에 의해 작성됨
지금쯤이면 당신은 아마 Pinia가 Vue.js의 공식적인 상태 관리 라이브러리로 인정되었다는 것을 들어보셨을 겁니다. 심지어 Evan You는 Pinia를 사실상 Vuex 5 라고 언급했습니다. 그런데 왜 Vuex 대신 Pinia를 사용해야 하는지, 그리고 어떻게 Pinia를 사용해야 하는지 알고 계신가요? 이 글에서는 Vuex와 Pinia의 경쟁에서, 왜 Pinia가 Vue 앱 상태 관리의 분명한 승자인지를 설명하려고 합니다. 하지만 그 전에, 몇 가지 짚고 넘어갈 배경지식과 질문들이 있습니다.
Pinia는 Vue 코어 팀의 멤버로 Vue Router를 개발한 Eduardo San Martin Morote에 의해 만들어졌습니다.
네. Pinia는 Vue.js 프레임워크의 두 주요 버전과 모두 호환됩니다.
자, 이제부터 Pinia를 Vuex보다 더 나은 선택으로 만들어주는 Pinia의 가장 흥미로운 특징들에 대해 알아보겠습니다.
Pinia의 API는 Vuex보다 간단하며, 더 직관적입니다. Vuex에서 매번 상태 변경 시에 작성해야 했던 많은 보일러플레이트 코드가 Pinia에서는 제거되었습니다. 따라서 주니어 개발자라도 훨씬 쉽게 상태 관리를 시작할 수 있습니다.
Pinia 예제를 살펴보겠습니다. Pinia를 Vue 앱에 설치하려면 터미널에 간단히 아래의 명령어를 입력하면 됩니다.
yarn add pinia
# or with npm
npm install pinia
Pinia를 사용하기 위해 main.js
를 업데이트합니다.
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const app = createApp(App);
app.use(createPinia());
app.mount("#app");
src
폴더 아래에 stores
폴더를 생성하고 counter.js
라는 파일을 생성한 뒤, 아래의 코드를 복사해서 붙여넣습니다.
📁src/stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => {
return { count: 0 };
},
actions: {
increment(value = 1) {
this.count += value;
},
},
getters: {
doubleCount: (state) => {
return state.count * 2;
},
doublePlusOne() {
return this.doubleCount + 1
},
},
});
위의 코드에서 몇 가지 주목해야 할 점이 있습니다.
store.$onAction()
을 활용하여 actions의 결과를 관찰하도록 구독할 수 있습니다.doublePlusOne
이 doubleCount
에 의존하는 것과 같이) this
를 사용하여 전체 store 인스턴스에 접근할 수 있습니다. 그러나 Pinia를 타입스크립트와 함께 사용할 땐, 화살표 함수로 정의된 getters나 this
를 사용하지 않는 getters에 영향을 미치지 못하는 타입스크립트의 한계점 때문에 반환 타입을 명시해줘야 합니다.이러한 변화들은 Pinia 코드를 Vuex에 비해 더 쉽게 읽고 이해할 수 있게 해줍니다.
Vuex에서는 내부에 여러 개의 모듈을 가질 수 있는 단일 store가 제공됩니다. 반면에 Pinia에서는 필요한 컴포넌트에서 바로 가져와서 사용할 수 있는 store를 여러 개 생성할 수 있습니다. 이러한 특징은 번들러의 코드 스플릿과 타입스크립트 추론이 더 나아지도록 돕습니다.
여러 개의 store를 가질 수 있는 특징은 개발 과정 또한 단순화했습니다. Vuex에서 매번 전체 store를 사용하는 것과 달리 store(또는 모듈)의 메서드만 사용하면 되기 때문입니다.
앞서 언급한 Pinia 예제를 단일 파일 컴포넌트에 적용해보면 다음과 같은 모습일 것입니다.
<script setup>
import { useCounterStore } from "./stores/counter";
const store = useCounterStore();
</script>
<template>
<h1>Count is {{ store.count }}</h1>
<h2>Double is {{ store.doubleCount }}</h2>
<button @click="store.increment()">Increment</button>
</template>
Vuex에 익숙하시다면 아마 Vue DevTools의 Vuex 탭을 잘 활용하셨을 것입니다. 그리고 Vuex actions와 mutations의 분리는 Vuex에서의 상태 변화를 추적하기 위해 Devtools와 연결되어있는 것이 mutations라는 걸 의미한다는 것을 알아차렸을 수도 있습니다. 그러면 다음과 같은 궁금증이 생길 수 있습니다. Pinia는 devtools를 가지고 있을까요?
다행히도 정답은 '네' 입니다. Pinia devtools는 이미 친숙한 Vuex devtools 만큼 유용합니다. 그리고 Vue 앱에 Pinia를 설치하면 바로 사용할 수 있습니다.
Vue 개발자들에게 Vuex가 타입을 지원하도록 하는 것은 항상 고통스러운 경험이었을 겁니다. Pinia는 이러한 문제점을 제거한 완전히 타입화된 상태 관리 라이브러리입니다. 타입 안전성은 잠재적인 런타임 에러 방지와 같은 많은 이점을 제공합니다. 타입스크립트를 활용해서 앱을 개발하고 있지 않더라도, Pinia의 재설계된 개발자 경험을 통해 자동 완성(auto-completion)이나 자동 제안(auto-suggestion)과 같은 큰 이점을 얻을 수 있습니다.
이러한 기능을 활용하기 위해 상태를 정의할 때 화살표 함수를 사용하시기를 권장합니다. 이를 통해 Pinia에서 타입 추론을 더 잘 지원받을 수 있습니다.
Pinia의 타입스크립트 지원은 당신이 상태에 대한 인터페이스를 정의할 수 있고, actions와 타입 정의를 통합하고, actions가 어떤 인자를 받는지에 대한 자동화된 문서를 받아와서, 자동 제안이나 자동 완성으로 코드를 마무리 지을 수 있다는 의미입니다.
Pinia와 타입스크립트를 함께 사용한 예제
interface ToDoItem {
item: string;
id: number;
done: boolean;
}
export const useTodoStore = defineStore('ToDoStore', {
state: () => ({
todos:[] as ToDoItem[]
}),
actions: {
addTodo(item: string) {
this.todos.push({ item, id: this.id++, done: false })
}
}
})
Pinia는 앞으로의 Vue 앱을 위한 상태 관리 솔루션으로 인정받았지만, 이는 더 이상 Vuex가 사용되지 않는다는 의미는 아닙니다. 만약 Vuex를 사용하는 앱이 프로덕션에서 운영되고 있다면, 애플리케이션은 여전히 잘 동작할 것이고, 라이브러리를 마이그레이션하는 것은 큰 비용이 들기 때문에 Vuex를 계속 사용하기를 권장합니다.
하지만, 당신의 프로젝트가 개발 초기 단계라면 Pinia를 사용하는 것이 좋습니다. 이 글에서 다룬 Pinia의 여러 특징 중 이해하기 쉬운 구문과 단순함의 이점을 누릴 수 있을 것입니다.
만약 Vuex에서 Pinia로 마이그레이션을 하고 싶다면 Vue 코어 팀의 멤버인 Ben Hong 이 설명하는 이 강좌를 들어보세요. 또한 Pinia의 창시자인 Eduardo San Martin의 유익한 Q&A 세션 을 시청하셔도 좋습니다. 이 세션에서 그는 Pinia와 일반적인 상태 관리에 대한 매우 흥미로운 질문들에 답변합니다. 그는 또한 라이브 데모에서 VueUse의 useLocalStorage
composable로 로컬 스토리지를 사용하여 어떻게 Pinia에서 상태를 유지할 수 있는지 보여줍니다.
Pinia는 빠르게 Vue 커뮤니티에서 입지를 굳히고 있으며, 우리는 위의 강좌들이 Pinia를 시작하기에 가장 좋은 방법이라고 생각합니다.
이번 글도 넘 재밌습니다! ☺️