Pinia

Pinia 1

Hoon1994 2022. 8. 25. 17:50

Pinia logo

 

Pinia란? 

Vue 버전 2를 사용할 때는 주로 상태 관리를 Vuex로 처리했는데, Vue3 or Composition API이 출시되면서 Pinia라는 상태 관리 모듈이 추가되었다. Vuex의 단점으로는 TS와 같이 설계하기가 어려움이 있었는데 (문법이나 Type 등에서), 이 점이 많이 개선되었다고 한다. 
그 외에도 장점이 꽤 많은 것 같은데, 공식 문서를 기반으로 Pinia의 장점은 무엇이 있는지 알아보자.

 


공식 문서 소개 페이지에 있는 내용이다. 직관적이고, 안전하고, Devtools 지원에, 확장, 모듈식, 가벼움 등등의 장점이 적혀있다. 
이 내용만 보고서는 Vuex와 비교 했을 때 정확히 어떤 차이가 있고 어느 정도 더 좋은지 알기 어려운듯 싶다. 직접 사용해보면서 겪어보자!


// npm i pinia

import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

const pinia = createPinia();
const app = createApp(App);

app.use(pinia);

app.mount('#app')


Vue3 프로젝트를 생성하고 pinia를 설치했다. pinia를 사용하기 위해서는 main.js에 app.use를 통해 등록해줘야 한다.

등록 후에는 store 폴더에 파일을 만들어서 모듈처럼 사용이 가능하다. 

 

export const useStore = defineStore('counter', {
    state: () => ({ count: 0 }),
    getters: {
        doubleCount: state => state.count * 2
    },
    actions: {
        increment() {
            this.count ++;
        }        
    }
})

 

위 코드는 state, getters, actions를 선언하여 사용하는 방식인데 Vuex와 매우 비슷하다.
mutations가 없는데 pinia에서는 mutations을 사용하지 않는다고 한다.
위 방식이 외에 Composition API와 비슷한 방식으로도 사용이 가능하다. 

 

import { defineStore } from "pinia";
import { computed, ref } from "vue";

export const useCounterStore = defineStore('counter', () => {
    const count = ref(2);
    const name = ref('ethan');
    const doubleCount = computed(() => count.value * 2);
    const increment = () => count.value++;

    return { count, name, doubleCount, increment };
})


Composition API 혹은 Vue3을 사용해보신 분이라면 굉장히 익숙하게 다가올 코드다. Composable처럼 정의하여 사용이 가능하다.
이렇게 사용할 경우 Vue Devtools에서 state, getters 구분이 되나? 싶은데 실제로 테스트 해봤을 때 구분이 된다. 
똑똑하네...

 

Vue devtools

Component에서는 어떻게 사용하는지 살펴보자. Store 뿐만 아니라 Props 등 Vue에서는 변수 선언 시 반응형이 깨지지 않도록
신경을 써줘야한다.

 

  setup() {
    const counterStore = useCounterStore();
    const { increment, name, count, doubleCount  } = counterStore;

    return {
      name,
      count, 
      doubleCount,
      increment
    }
  }


만약 위 코드처럼 구조분해할당을 통해 변수를 선언하고 return 해줄 경우 imcrement를 통해
count 값을 변경해도 화면에서는 변경되지 않는다. 

 


스크린 샷을 보면 화면에는 2,4로 표시되지만 실제 pinia에는 12,24로 되어 있는 걸 볼 수 있다. 

그러면 반응형이 깨지지 않도록 하려면 어떻게 해야 할까? 아래처럼 작성하면 된다.

 

  setup() {
    
    const counterStore = useCounterStore();
    const { name, count, doubleCount } = storeToRefs(counterStore);
    const { increment } = counterStore;

    return {
      name, count, doubleCount,
      increment
    }
  }

 

storeToRefs 안에 store를 넘겨준 후 구조분해할당을 통해 가져올 경우 반응형이 꺠지지 않아서 정상적으로 동작이 된다.

 


SSR 환경에서는 설정 방법이 조금 다른 것 같은데, 다음 포스팅에서는 SSR 환경 및 더욱 심화적인 내용을 작성할 예정이다.