
뭔가 복잡하지만 익숙해지면 이게 코드 관리하기 좋구나라는 생각을 하게 됨.
아닐 수도 있지만 결국 프로젝트 커지면 pinia는 필수.
예전 Vuex에서는 state 수정을 위해 mutations를 사용하고, 서버에서 데이터를 가져와 state를 변경할 때는 ajax 같은 비동기 작업을 actions에 작성하도록 권장했습니다.
왜냐하면, mutations에 비동기 코드를 넣으면 실행 순서가 엉켜 의도치 않은 버그가 발생할 수 있기 때문입니다.
기존 Vuex 방식
- mutations: 순수하게 state 변경만 수행
- actions: ajax 등 비동기 작업 후, 필요한 경우
context.commit()을 통해 mutations 호출
Pinia는 이러한 패턴을 더욱 단순하게 만듭니다.
Pinia에서는 mutations가 필요 없으며, state는 actions 내에서 직접 변경할 수 있습니다.
즉, 비동기 작업과 state 변경을 한 곳에서 처리할 수 있어 코드가 깔끔해집니다.
name 데이터를 업데이트하는 ajax 요청이 3초 이상 걸린다면, 바로 이어서 실행되는 age 업데이트 함수보다 늦게 완료되어 의도하지 않은 순서로 state가 변경될 수 있습니다.아래는 사용자 데이터를 관리하는 Pinia 스토어 예시입니다.
여기서 actions는 비동기 작업(예: axios를 통한 데이터 요청) 후 state를 직접 업데이트합니다.
<!-- stores/user.js -->
<script setup>
import { defineStore } from 'pinia'
import axios from 'axios'
export const useUserStore = defineStore('user', {
// state는 함수로 반환합니다.
state: () => ({
name: '',
age: null,
}),
// actions 내에서 비동기 작업을 수행할 수 있습니다.
actions: {
async fetchUserData() {
try {
// ajax 요청 (axios 사용)
const response = await axios.get('https://api.example.com/user')
// 비동기 요청 후, state를 직접 업데이트합니다.
this.name = response.data.name
this.age = response.data.age
} catch (error) {
console.error('데이터를 가져오는 데 실패했습니다.', error)
}
},
// 여러 데이터 변경 작업을 순차적으로 실행할 때도 actions에서 관리합니다.
async updateNameAndAge() {
// 예시: name과 age 데이터를 순차적으로 변경하고 싶을 때
await this.fetchUserData() // name 업데이트 후
// 만약 추가 작업이 필요하다면 여기서 계속 실행
// 예: this.age = 수정된값
}
}
})
</script>
Vue3의 <script setup> 문법을 사용하여 스토어의 액션을 호출하는 예시입니다.
<!-- App.vue -->
<script setup>
import { useUserStore } from './stores/user'
const userStore = useUserStore()
// 액션 호출 (Vuex의 $store.dispatch 대신 store의 메서드를 직접 호출)
userStore.fetchUserData()
</script>
<template>
<div>
<p>Name: {{ userStore.name }}</p>
<p>Age: {{ userStore.age }}</p>
</div>
</template>
핵심 정리:
- Pinia에서는 actions 내에서 비동기 요청(ajax 등)을 수행하고, 완료되면 state를 직접 변경합니다.
- Vuex와 달리 mutations가 분리되어 있지 않으므로,
commit()없이this를 통해 직접 state에 접근합니다.- 컴포넌트에서는
store.fetchUserData()처럼 액션을 직접 호출하여 데이터를 가져옵니다.
commit으로 mutations 호출)