판다꼬마 2024. 6. 11. 12:19
728x90

Pinia란?

Pinia는 Vue3에 필요한 Composition API 기반으로 사용할 수 있는 상태 관리라이브러리입니다.

기존 Vue에서 사용하던 상태관리는 Vuex였는데 Pinia가 공식적으로 추천하는 상태 관리 라이브러리가 되었습니다. 

이번 프로젝트에서 Nuxt3를 적용하기 때문에 Pinia를 채택해 공부하는 중입니다.

 

https://pinia.vuejs.kr/

 

Vue 3의 공식 Store | Vue.js를 위한 직관적인 스토어

직관적이고 타입 안전한 가벼운 그리고 유연한 Vue 스토어

pinia.vuejs.kr

 

 

Pinia의 장점

  1. 타입스크립트 기반으로 타입에 대한 안정성이 보장이 된다.
  2. 가벼운 용량
  3. 모듈식 디자인으로 모듈화
  4. 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 };
});

 

728x90