조아마시

쓸모 있는 상세페이지 만들기

웹개발/vuejs

[Vue] pinia 직관적인 Vue.js 상태 관리 라이브러리

joamashi 2024. 8. 7. 22:00

Pinia는 Vue.js 3에서 사용되는 상태 관리 라이브러리입니다. 기존의 Vuex를 대체하거나 보완하여 더욱 간결하고 효율적인 상태 관리를 가능하게 해줍니다. Pinia는 Composition API를 기반으로 설계되어 Vue.js 3의 반응형 시스템과 잘 어울리며, TypeScript와의 통합도 뛰어납니다.

왜 Pinia를 사용해야 할까요?

  • 간결한 API: Vuex에 비해 더 간결하고 직관적인 API를 제공하여 코드 작성이 쉽습니다.
  • Composition API 기반: Composition API를 활용하여 코드 재사용성을 높이고 가독성을 향상시킵니다.
  • TypeScript 지원: TypeScript와의 뛰어난 통합으로 안전하고 강력한 타입 시스템을 제공합니다.
  • 모듈화: 각 기능별로 Store를 분리하여 관리할 수 있어 코드 관리가 용이합니다.
  • Hot Module Replacement (HMR): HMR을 지원하여 개발 시 실시간으로 변경 사항을 반영할 수 있습니다.
  • Vue Devtools 지원: Vue Devtools를 통해 상태를 시각적으로 확인하고 디버깅할 수 있습니다.

Pinia의 주요 구성 요소

  • Store: 상태를 저장하고 관리하는 객체입니다.
  • State: 실제 상태 데이터를 저장하는 프로퍼티입니다.
  • Actions: 상태를 변경하는 함수입니다.
  • Getters: 상태를 계산하여 반환하는 함수입니다.
 

Pinia의 장점

  • 학습 곡선이 낮음: Vue.js를 이미 알고 있다면 Pinia를 배우는 데 어렵지 않습니다.
  • 유연성: 다양한 프로젝트에 적용할 수 있도록 유연한 구조를 가지고 있습니다.
  • 활발한 커뮤니티: 많은 개발자들이 사용하고 있으며, 활발한 커뮤니티를 통해 다양한 정보를 얻을 수 있습니다.

언제 Pinia를 사용해야 할까요?

  • 복잡한 상태 관리가 필요한 경우: 여러 컴포넌트에서 공유되는 데이터를 관리해야 할 때 Pinia를 사용하면 효과적입니다.
  • TypeScript를 사용하는 경우: TypeScript와의 뛰어난 통합으로 안전하고 강력한 타입 시스템을 활용할 수 있습니다.
  • Vue.js 3 프로젝트: Vue.js 3 프로젝트에서 Composition API를 사용하고 있다면 Pinia와의 시너지 효과를 기대할 수 있습니다.

더 자세한 정보는 어디에서 얻을 수 있나요?

 

시작하기

npm install pinia
npm install pinia-plugin-persistedstate
// plugins/index.js

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

export function registerPlugins(app) {
  app.use(pinia)
}

// main.js
import { registerPlugins } from '@/plugins'
import App from './App.vue'

import { createApp } from 'vue'
const app = createApp(App)
registerPlugins(app)
app.mount('#app')

기본적인 Store 예시

// @/stores/counter.js

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', { // 상태를 저장하고 관리하는 객체
  persist: true, // 해당 Store의 모든 상태가 로컬 스토리지에 저장
  state: () => ({ // 실제 상태 데이터를 저장하는 프로퍼티
    count: 0
  }),
  getters: { // 상태를 계산하여 반환하는 함수
    doubleCount: (state) => state.count * 2,
  },
  actions: { // 상태를 변경하는 함수
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    }
  }
})

컴포넌트에서 state 사용하기

<template>
  <div>
    <p>현재 카운트: {{ count }}</p>
    <p>Double count is {{ counterStore.doubleCount }}</p>
    
    <button @click="counterStore.decrement()">감소</button>
    <button @click="counterStore.increment()">증가</button>
  </div>
</template>

<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from './stores/counter'

const counterStore = useCounterStore()
const { count } = storeToRefs(counterStore)
</script>

Pinia-plugin-persistedstate란 무엇인가요?

Pinia-plugin-persistedstate는 Pinia에서 사용하는 플러그인으로, Store의 상태를 로컬 스토리지나 세션 스토리지에 저장하고 복원하는 기능을 제공합니다. 이를 통해 사용자가 브라우저를 새로 고침하거나 다른 페이지로 이동하더라도 이전 상태를 유지할 수 있습니다.

예를 들어, 사용자가 Todo 리스트 앱에서 Todo 항목을 추가하고 페이지를 새로 고쳐도 Todo 목록이 그대로 유지되는 것을 구현할 수 있습니다.

왜 Pinia-plugin-persistedstate를 사용해야 할까요?

  • 사용자 경험 향상: 사용자가 앱을 다시 시작하더라도 이전 작업 상태를 유지하여 편리한 사용 환경을 제공합니다.
  • 개발 편의성: 개발자가 상태를 직접 저장하고 복원하는 로직을 구현할 필요가 없어 개발 시간을 단축시킵니다.
  • 유연성: 다양한 저장소(localStorage, sessionStorage 등)를 사용할 수 있으며, 저장할 데이터를 선택적으로 지정할 수 있습니다.
  1. Store에 설정 추가
  2. persist: true 옵션을 추가하면 해당 Store의 모든 상태가 로컬 스토리지에 저장됩니다.
    import { defineStore } from 'pinia'
    
    export const useCounterStore = defineStore('counter', {
      state: () => ({
        count: 0
      }),
      persist: true
    })
    

주요 기능 및 설정

  • 저장소 선택: localStorage, sessionStorage 외에도 다른 저장소를 사용할 수 있습니다.
  • 저장 데이터 선택: 저장할 state의 프로퍼티를 지정할 수 있습니다.
  • Serializer: 저장하기 전에 데이터를 변환하는 함수를 사용할 수 있습니다.
  • Hydration: 저장된 데이터를 복원하는 과정에서 발생할 수 있는 오류를 처리하는 기능을 제공합니다.

추가 설정 예시

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '',
    age: 0,
    isLoggedIn: false
  }),
  persist: {
    storage: localStorage,
    paths: ['name', 'isLoggedIn'], // name과 isLoggedIn만 저장
    serializer: {
      encode: (state) => JSON.stringify(state),
      decode: (state) => JSON.parse(state)
    }
  }
})

위 예시에서는 name과 isLoggedIn 프로퍼티만 localStorage에 저장하고, JSON 형식으로 직렬화하여 저장합니다.

주의사항

  • 성능: 너무 많은 데이터를 저장하면 성능 저하가 발생할 수 있습니다. 필요한 데이터만 저장하도록 주의해야 합니다.
  • 보안: 민감한 정보를 localStorage에 저장하는 것은 보안상 위험할 수 있습니다.
  • 브라우저 호환성: 모든 브라우저에서 localStorage와 sessionStorage를 완벽하게 지원하지 않을 수 있습니다.

비동기 데이터 불러오기 

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useDataStore = defineStore('data', () => { // 화살표 함수 사용
  const data = ref([])
  const isLoading = ref(false)

  const fetchData = async () => {
    isLoading.value = true
    
    try {
      const res = await getDataAPI()
      data.value = res
    } catch (error) {
      console.log('API 호출 실패')
    } finally {
      isLoading.value = false
    }
  }

  const pData = computed(() =>
    data.value.map((d) => ({
      id: d.id,
      content: d.url,
      name: d.side,
    }))
  )

  const nameData = computed(() => {
    return [...new Set(data.value.map((d) => d.name))]
  })

  return { 
    isLoading, 
    pData, 
    nameData, 
    fetchPhotos 
  };
});

/

728x90