Pinia란?
Pinia란?
Pinia는 Vue3에 필요한 Composition API 기반으로 사용할 수 있는 상태 관리라이브러리입니다.
기존 Vue에서 사용하던 상태관리는 Vuex였는데 Pinia가 공식적으로 추천하는 상태 관리 라이브러리가 되었습니다.
이번 프로젝트에서 Nuxt3를 적용하기 때문에 Pinia를 채택해 공부하는 중입니다.
Vue 3의 공식 Store | Vue.js를 위한 직관적인 스토어
직관적이고 타입 안전한 가벼운 그리고 유연한 Vue 스토어
pinia.vuejs.kr
Pinia의 장점
- 타입스크립트 기반으로 타입에 대한 안정성이 보장이 된다.
- 가벼운 용량
- 모듈식 디자인으로 모듈화
- Devtools 지원
시작해보기
설치
yarn add pinia
스토어 설정
/store/index.ts
import { defineStore } from 'pinia';
export const useMyStore = defineStore('firstStore', () => {
const message = ref('Hello');
return { message };
});
nuxt.config.ts 설정
export default defineNuxtConfig({
devtools: { enabled: true },
typescript: {
typeCheck: false
},
modules: ['@pinia/nuxt']
});
modules에 '@pinia/nuxt'만 추가해 주면 기본적인 설정을 완료되었다.
컴포넌트에서 사용해 보기
<template>
<div>
{{ store.message }}
</div>
</template>
<script setup lang="ts">
import { useMyStore } from '~/stores';
const store = useMyStore();
</script>
Store 설정하기
export const useMyStore = defineStore('firstStore', () => {
const message = ref('Hello');
return { message };
});
store는 defineStore를 통해서 정의할 수 있고 변수의 이름은 use~~~ 로 지어야 하는 것이 좋다. 또한 첫 번째 인자로 store의 고유 값을 정하기 위해 변수를 설정해줘야 한다. 두 번째 인자에는 Setup 함수 or Options 객체가 들어올 수 있다.
Option Stores
Options API를 사용하는 것과 비슷하게 state, actions, getters 속성을 사용하여 Options 객체를 전달한다.
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0, name: 'Eduardo' }),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
간단하게 말하면 요약하면
state => 스토어의 data
getter => 스토어의 computed
actions => methods
Setup Stores
Composition API를 사용하는 것과 비슷하게 작성을 하여 스토어를 작성하면 된다.
export const useCounterStore = defineStore('counter', () => {
const count = ref(0);
const name = ref('Eduardo');
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, name, doubleCount, increment };
});
간단하게 요약하면
ref() => state 속성
computed() => getters
function() => actions
이렇게 생각을 하면 된다.
작성한 Store 이용해 보기
<script setup>
import { useCounterStore } from '@/stores/counter'
// 컴포넌트 어디에서나 `store` 변수에 액세스
const store = useCounterStore()
</script>
use... Store()로 호출을 하여 스토어를 정의한 후 사용하면 된다.
Options API vs Composition API
Pinia는 기존 vue2에서 사용하던 Options API를 사용하여 코드를 작성하는 방법과 Vue3에 새로 도입된 Composition API에서 setip 함수를 사용하여 코드를 작성하는 방법 둘 다 지원을 합니다. 저는 개인적으로 Composition API를 사용하여 작성하는 것을 좋아합니다. 기존 Vue2에 익숙하신 분들은 그대로 작성하셔도 될 것 같으나 새로 배워보시는 분들은 Composition API를 사용해 작성하는 것을 추천드립니다!
Options API와 Composition API는 다른 글에 자세히 정리해 놓겠습니다.
Options API
import { defineStore } from 'pinia';
import type { UserData } from '~/types/user/User';
export const useUserStore = defineStore('userInfo', {
persist: true,
state: () => ({
user: {
userId: null,
id: null,
name: '',
email: '',
isLoggedIn: false
} as UserData
}),
getters: {
getUserState: state => state.user,
userId: state => state.user.userId,
isUserLoggedIn: state => state.user.isLoggedIn
},
actions: {
setUser(user: Partial<UserData>) {
this.user = { ...this.user, ...user };
},
clearUser() {
this.user = {
userId: null,
id: null,
name: '',
email: '',
isLoggedIn: false
};
}
}
});
Composition API
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import type { UserData } from '~/types/auth/user';
export const useUserStore = defineStore('userInfo', () => {
const user = ref<UserData>({
userId: null,
id: null,
name: '',
email: '',
isLoggedIn: false
});
const getUserState = computed(() => user.value);
const userId = computed(() => user.value.userId);
const isUserLoggedIn = computed(() => user.value.isLoggedIn);
function setUser(userData: Partial<UserData>) {
user.value = { ...user.value, ...userData };
}
function clearUser() {
user.value = {
userId: null,
id: null,
name: '',
email: '',
isLoggedIn: false
};
}
return { user, getUserState, userId, isUserLoggedIn, setUser, clearUser };
});