Pinia๋ ๋ฌด์์ธ๊ฐ
Pinia๋ Vue 3์์ ๊ณต์์ ์ผ๋ก ๊ถ์ฅํ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
์ด์ ๊น์ง Vue์ ์ํ ๊ด๋ฆฌ๋ Vuex๊ฐ ์ฌ์ค์ ํ์ค์ด์์ง๋ง, Vue 3 ์ดํ๋ก๋ Pinia๊ฐ ์๋ก์ด ๊ณต์ ๋์์ด ๋์๋ค.
Vuex์ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๋์ฒดํ๊ธฐ ์ํด ์ค๊ณ๋์์ผ๋ฉฐ,
Composition API์ ๋ง์ถฐ ๊ฐ๋ณ๊ณ ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ์ํ๋ฅผ ์ ์ํ๊ณ ์ฌ์ฉํ ์ ์๊ฒ ํ๋ค.
ํต์ฌ์ ์ผ๋ก Pinia๋ ์๋ ์ธ ๊ฐ์ง๋ก ์ํ ๊ด๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ค:
- state: ๊ณต์ ํ ๋ฐ์ดํฐ
- getters: ๊ณ์ฐ๋ ๊ฐ (computed)
- actions: ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ํจ์ (methods)
๊ธฐ๋ณธ ์ค๊ณ ์ฒ ํ์ ๋จ์ํจ, ํ์ ์์ ์ฑ, Composition API ์นํ์ ๊ตฌ์กฐ๋ค.
์ Vuex ๋์ Pinia์ธ๊ฐ
Vuex๋ mutations, actions, modules, strict mode, mapXXX helpers ๋ฑ ๋ณต์กํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์๋ค.
์์ ํ๋ก์ ํธ์์๋ ์๋ง์ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๊ฐ ํ์ํ๋ค. ๋ฐ๋ฉด, Pinia๋ ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ์ด ์๋ค.
- Mutation ์์ด ์ง์ state ๋ณ๊ฒฝ ๊ฐ๋ฅ
Vuex๋ commit()์ ํตํด์๋ง state๋ฅผ ๋ฐ๊ฟ ์ ์์์ง๋ง, Pinia๋ ๊ทธ๋ฅ this.count++ ํ๋ฉด ๋๋ค. - ํ์
์คํฌ๋ฆฝํธ ์๋ ์ง์
๋ณ๋ ์ค์ ์์ด๋ ํ์ ์ถ๋ก ์ด ๊น๋ํ๊ฒ ๋์ํ๋ค. - Composition API์ ์๋ฒฝํ ํธํ
defineStore()๋ฅผ Composition API ์์์ ๋ฐ๋ก ์ธ ์ ์๋ค. - ๋ชจ๋ ์์คํ
์ด ๊ธฐ๋ณธ๊ฐ
store๋ฅผ ์ฌ๋ฌ ๊ฐ๋ก ๋๋ ์ ์๊ณ , ๊ฐ store๋ ๋ ๋ฆฝ์ ์ผ๋ก ์๋ํ๋ค.
์ค์น ๋ฐ ์ค์
npm install pinia
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
๊ธฐ๋ณธ ์คํ ์ด ์ ์ ์์
// src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
name: 'Vue'
}),
getters: {
doubleCount: (state) => state.count * 2,
greeting: (state) => `Hello, ${state.name}`
},
actions: {
increment() {
this.count++
},
setName(newName) {
this.name = newName
}
}
})
- defineStore('counter', {...})์์ 'counter'๋ ์ด ์คํ ์ด์ ๊ณ ์ ID์ด๋ค.
- state๋ ํจ์๋ก ์ ์ํ๋ฉฐ, ๋ฐํํ ๊ฐ์ฒด๊ฐ ๋ฐ์ํ์ผ๋ก ๊ด๋ฆฌ๋๋ค.
- getters๋ computed์ฒ๋ผ ๋์ํ๋ค.
- actions๋ methods์ฒ๋ผ ์ฌ์ฉํ๋ค. ๋น๋๊ธฐ ํจ์๋ ๊ฐ๋ฅํ๋ค.
์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๊ธฐ
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.increment()
</script>
<template>
<p>{{ counter.count }}</p>
<p>{{ counter.doubleCount }}</p>
<button @click="counter.increment">+1</button>
</template>
store๋ Composition API ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฏ๋ก useCounterStore()๋ก store ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์จ๋ค.
์ด ์ธ์คํด์ค๋ ์ ์ญ์์ ๊ณต์ ๋๋ฉฐ ์ฑ๊ธํค์ด๋ค.
๋น๋๊ธฐ ์ฒ๋ฆฌ ์์
actions: {
async fetchUser() {
const res = await fetch('/api/user')
const data = await res.json()
this.name = data.name
}
}
actions ์์์๋ async/await๋ฅผ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์๋ค. ์ด๋ Vuex๋ณด๋ค ํจ์ฌ ์ง๊ด์ ์ธ ๊ตฌ์กฐ๋ค.
๋ชจ๋ ๊ตฌ์กฐ๋ก ํ์ฅ
ํ๋ก์ ํธ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก store๋ ๊ธฐ๋ฅ๋ณ๋ก ๋๋๋ค.
stores/
โโโ auth.js
โโโ user.js
โโโ todo.js
๊ฐ๊ฐ defineStore()๋ก ๋ง๋ค๊ณ , ํ์ํ ๊ณณ์์ useAuthStore(), useTodoStore() ๋ฑ์ผ๋ก ๊บผ๋ด ์ด๋ค.
๋๋ฒ๊น ๊ณผ DevTools
Pinia๋ Vue DevTools์ ์๋ฒฝํ๊ฒ ์ฐ๋๋๋ค.
์ํ ๋ณํ ์ถ์ , time-travel debugging, ์ํ snapshot ์ ์ฅ, mutation ๋ก๊ทธ ๋ฑ์ ์ง์ํ๋ค.
Vuex์ฒ๋ผ ๋ณ๋ ์ค์ ์์ด ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
๋ง๋ฌด๋ฆฌ
Pinia๋ Vue 3์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์๋ก์ด ๊ธฐ๋ณธ๊ฐ์ด๋ค.
Vuex๋ณด๋ค ๊ฐ๋ณ๊ณ , ์ฝ๋๊ฐ ๊ฐ๊ฒฐํ๋ฉฐ, Composition API์์ ๊ฒฐํฉ์ด ์ ์ฐํ๋ค.
์์ ํ๋ก์ ํธ๋ถํฐ ๋ํ SPA๊น์ง ๋ฌด๋ฆฌ ์์ด ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ, ๋ฌ๋ ์ปค๋ธ๊ฐ ๋ฎ์ ๋น ๋ฅด๊ฒ ๋์ ํ ์ ์๋ค.
Vue 3 ๊ธฐ๋ฐ์ ํ๋ก์ ํธ๋ฅผ ์์ํ๋ค๋ฉด ๋ณ๋ค๋ฅธ ๊ณ ๋ฏผ ์์ด Pinia๋ฅผ ๊ธฐ๋ณธ ์ํ ๊ด๋ฆฌ ๋๊ตฌ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ํฉ๋ฆฌ์ ์ด๋ค
'๐ป Frontend > Vue.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Vue 3 + Vite์์ Axios API ๊ตฌ์กฐ ์๋ฒฝ ๊ฐ์ด๋ (4) | 2025.06.05 |
---|---|
Vue.js 3 ์ปดํฌ์ง์ API ๊ธฐ๋ฐ ํ๋ก ํธ์๋ ํ๋ก์ ํธ ๊ตฌ์กฐ ์ดํด (3) | 2025.06.02 |