Dewdew logo-mobile
Uses
Tech
방명록
포트폴리오

Pinia: Vue3 상태 관리 Pinia를 효과적으로 사용하는 방법

Vue Nation 2024 세션 요약: Vuex와 같이 Pinia를 사용하지 않는 방법을 논의합니다.

vue3 vue nation 2024 pinia
dewdew

Dewdew

Jan 26, 2024

6 min read

cover

Pinia란?

PiniaVue3 & Nuxt3에서 상태 관리 라이브러리로, Vuex와 유사한 기능을 제공합니다.

Vuex와 달리, Pinia는 상태 관리에 Composition API를 사용합니다. 또한, mutation, action, getter 등의 개념 없이 Store 값을 반응형으로 사용할 수 있습니다.

과거에는 Vuex가 널리 사용되었지만, Vue3에서는 Pinia가 주로 사용됩니다.

Vue Nation 2024 세션에서, Pinia 크리에이터인 Eduardo San Martin Morote는 Pinia를 효과적으로 사용하는 방법에 대한 세션을 진행했습니다. 다음 내용은 세션에서 얻은 인사이트를 공유합니다.


1.Mutation 필요 없음

Vuex에서는 state, mutations, actions, getters를 통해 전역 상태를 관리할 수 있습니다.

// vuex
const store = createStore({
  state: () => ({
    count: 0,
    isHidden: true
  }),
  mutations: {
    increment(state) {
      state.count++
    },
    toggle(state) {
      state.isHidden = !state.isHidden
    }
  }
})

// getting state value in component
store.state.count
store.state.isHidden

// mutation in component
store.commit('increment')
store.commit('toggle')

Vuex에서는 상태를 변경하기 위해서는 mutation을 사용해야 했습니다. 하지만, Pinia에서는 직접 state를 변경할 수 있습니다.

// pinia
const useToggleStore = defineStore('toggle', {
  const count = ref(0)
  const isHidden = ref(true)

  return {
    count,
    isHidden
  }
})

// mutaions in component
const { count, isHidden } = sotreToRefs(useToggleStore())
count.value++
isHidden.value = false

2.Pinia의 다양한 장점

Pinia는 다음과 같은 장점을 가지고 있습니다.

  • Pinia는 Type safety를 지원합니다.
  • Pinia는 모듈화된 Store를 지원합니다.
  • Pinia는 더 나은 코드 분할을 지원합니다.
  • Pinia는 Composition API를 사용합니다.

3.타입 관리

Vuex에서는 타입 관리가 다음과 같이 스토어 외부에서 이루어졌습니다.

// wrong
cosnt state: State = {
  //...
}

defineStore('...', {
  state: () => state,
})

하지만, Pinia에서는 위와 같이 하지 말고, 아래와 같이 스토어 내부에서 types를 직접 지정해야 합니다.

// correct
defineStore('...', {
  state: (): State => ({
    //...
  })
})

4.읽기 전용 Store

Pinia에서 read-only store를 구축하려면, 다음과 같이 코드 예제를 수정해야 합니다.

// before
const useStore = defineStore('...', {
  const user = ref()

  return {
    // no Plugins, devtools, SSR
    userReadonly: readonly(user),
    // not state
    get userGetter () {
      return user.value
    },
    // not state
    userComputed: computed(() => user.value)
  }
})
// after
const useStore = defineStore('...', {
  const user = ref()

  return {
    _user: user,
    // valid gatter
    user: computed(() => user.value)
  }
})

또는, 아래와 같이 Private Store를 생성하여 관리할 수 있습니다. 이를 통해, 특정 스토어 내에서만 사용할 수 있는 변수를 생성할 수 있습니다.

const usePrivateStore = defineStore('...', {
  const user = ref()

  return {
    user
  }
})

const userStore = defineStore('...', {
  const privateStore = usePrivateStore()

  privateStore.user // only within the store

  return {
    // no user exposed
  }
})

5.TypeScript

예제에서 보여드린 것처럼, 스토어에 대한 TypeScript를 작성할 때, 아래와 같이 ~ as를 사용하는 대신, generics를 사용하여 타입을 지정하는 것이 더 좋습니다.

// not good
const useUserStore = defineStore('user', {
  const userToken = ref({} as UserToken)
  const user = ref({} as User)

  return {
    userToken,
    user
  }
})
// good
const useUserStore = defineStore('user', {
  const userToken = ref<UserToken | null>(null) // For initialize with null
  const user = ref<User>() // For handling undefined

  return {
    userToken,
    user
  }
})

6.스크립트에서 Store 사용

아래 예제와 같이 사용하면, Pinia에서 오류가 발생합니다. Composition API를 사용할 때, setup 내에서 store를 한 번만 호출하면 됩니다.

// wrong
<script setup>
import { useModalStore } from './store/modal'

function someMethod () {
  const modalStore = useModalStore()
}

watch(something, () => {
  const modalStore = useModalStore()
})
</script>
// good
<script setup>
import { useModalStore } from './store/modal'
const modalStore = useModalStore()

function someMethod () {
  modalStore //
}

watch(something, () => {
  modalStore //
})
</script>

이제 프로젝트를 만들어봅시다!

저는 더 많은 정보를 얻었지만, 오늘 정리한 내용은 여기까지입니다!

현재 진행 중인 Vue nation 2024에는 훌륭한 세션들이 많이 있으며, 좋은 통찰력을 얻을 수 있는 좋은 기회라고 생각합니다. 유익한 정보를 얻어가시길 바래요.

다음에 봐요!


참고 문서

Dewdew of the Internet © 2024