[Vue3] Pinia : 3. actions 항목을 알아보자

gminnimk·2025년 3월 21일

Vue3

목록 보기
31/39

뭔가 복잡하지만 익숙해지면 이게 코드 관리하기 좋구나라는 생각을 하게 됨.

아닐 수도 있지만 결국 프로젝트 커지면 pinia는 필수.


1️⃣ 개요

예전 Vuex에서는 state 수정을 위해 mutations를 사용하고, 서버에서 데이터를 가져와 state를 변경할 때는 ajax 같은 비동기 작업을 actions에 작성하도록 권장했습니다.

왜냐하면, mutations에 비동기 코드를 넣으면 실행 순서가 엉켜 의도치 않은 버그가 발생할 수 있기 때문입니다.

기존 Vuex 방식

  • mutations: 순수하게 state 변경만 수행
  • actions: ajax 등 비동기 작업 후, 필요한 경우 context.commit()을 통해 mutations 호출

Pinia는 이러한 패턴을 더욱 단순하게 만듭니다.

Pinia에서는 mutations가 필요 없으며, state는 actions 내에서 직접 변경할 수 있습니다.

즉, 비동기 작업과 state 변경을 한 곳에서 처리할 수 있어 코드가 깔끔해집니다.


2️⃣ 왜 actions를 사용해야 할까?

  • 비동기 작업 관리: 서버에서 데이터를 가져오는 ajax 요청은 실행 시간이 다를 수 있습니다. 예를 들어, name 데이터를 업데이트하는 ajax 요청이 3초 이상 걸린다면, 바로 이어서 실행되는 age 업데이트 함수보다 늦게 완료되어 의도하지 않은 순서로 state가 변경될 수 있습니다.
  • 코드의 가독성 및 유지보수성 향상: state를 변경하는 코드는 순수하게 관리하고, ajax 요청 등 오래 걸리는 코드는 별도의 actions에 작성하여 코드 구조를 명확하게 유지할 수 있습니다.

3️⃣ Pinia에서의 Actions 사용법

3-1. Store 생성 예시

아래는 사용자 데이터를 관리하는 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>

3-2. 컴포넌트에서 store 액션 호출하기

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() 처럼 액션을 직접 호출하여 데이터를 가져옵니다.

📌 정리

  • Vuex와 Pinia 비교
    • Vuex:
      • state 변경 → mutations (동기적)
      • ajax 등 비동기 작업 → actions (이후 commit으로 mutations 호출)
    • Pinia:
      • mutations 개념 없음
      • state는 actions 내에서 직접 변경
      • 비동기 작업과 state 변경을 하나의 액션에서 관리 가능
  • 왜 actions를 분리하는가?
    • 비동기 작업(ajax 요청 등)이 오래 걸리면 실행 순서가 뒤바뀔 수 있음
    • 순수하게 state 변경만 수행하는 함수(혹은 코드 블록)를 따로 분리하면 유지보수가 쉬움
  • 사용 방법
    • Pinia를 사용하여 store를 정의하고,
    • 컴포넌트에서는 store의 액션을 호출하여 데이터를 비동기로 가져오고 state를 업데이트

0개의 댓글