본문으로 바로가기

Vuex (v4.x)

category JavaScript/Vue.js 2021. 7. 19. 13:56

Vuex란?

 - 복잡한 애플리케이션에서 컴포넌트 수가 많이지면 컴포넌트 간의 데이터 전달이 어려워진다. Vuex는 Vue.js 애플리케이션을 위한 상태관리 패턴 + 라이브러리이다.

 - 모든 컴포넌트에 대한 중앙집중식 저장소 역할을 하며 예측 가능한 방식으로 상태를 변경할 수 있다.

 

 - Vuex를 이용하지 않는다면 컴포넌트 간에 데이터를 주고받는 것은 방법은 있지만, 대규모 프로젝트가 될수록 매우 복잡해진다.

 - 데이터를 store에 저장하고, 프로젝트 전ㅊ에서 사용할 수 있도록 해주는 것이 Vuex이다.

 

Vuex 설치

 - 터미널에서 다음 명령어를 통해 설치한다.

npm install vuex@next --save

 

시작하기

 - 모든 Vuex 애플리케이션의 중심에는 store가 있다. 저장소(store)는 애플리케이션 상태를 저장하고 있는 컨테이너이다.

 

 - Vuex 저장소가 일반 전역 개체와 두 가지 다른 점이 있다.

 - Vuex store는 반응형이다. Vue 컴포넌트는 저장소의 상태(state)를 검색할 때 저장소의 상태에 정의된 변수 값의 변경 여부를 바로 알 수 있다.

 - 저장소의 상태를 직접 변경할 수 없다. 저장소의 상태를 변경하는 유일한 방법은 명시적인 커밋을 이용한 변이이다.

 - 이렇게 하면 모든 상태에 대한 추적이 가능한 기록이 남을 수 있으면 툴을 사용하여 앱을 더 잘 이해할 수 있다.

 

 - 아주 간단한 형태의 store를 하나 만들어보자

// src/store.js
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0
    }
  },
  mutations: {
    increment(state) {
      state.count++
    }
  }
})

export default store;

 - Vue 컴포넌트에서는 this.$store로 접근이 가능하다

// src/views/StoreAccess.vue
<template>
  <div>
    <p>Count : {{ count }}</p>
    <button type="button" @click="increment">Increment</button>
  </div>
</template>
<script>
  export default {
    computed: {
      count() {
        return this.$store.state.count
      }
    },
    methods: {
      increment() {
        this.$store.commit('increment')
      }
    }
  }
</script>

 - 여기서 저장소의 state에 바로 접근해서 변경하는 것이 아니라, commit을 통해서만 변경할 수 있다.

 

State

 - state는 프로젝트 전체에서 공통으로 사용할 변수를 정의하는 곳이다.

 - state에 변수를 정의함으로써 모든 컴포넌트에서 사용 가능하다.

 - state 관리를 통해 모든 컴포넌트에서 동일한 값을 사용할 수 있다.

 

 - state에서 정의된 변수는 Vue 컴포넌트에서는 computed 속성을 이용해서 그 변경사항을 항상 추적할 수 있다.

computed: {
  count() {
    return this.$store.state.count
  }
}

 

Getters

 - 우리가 쇼핑몰을 이용할 때를 생각해보자. 쇼핑몰 웹사이트에서 장바구니에 다음 제품의 수가 항상 화면 상단의 장바구니 아이콘에 표기되는 것을 보았을 것이다. 어떤 화면에서든지 제품을 장바구니에 추가하면 바로 장바구니 아이콘의 제품 수가 증가하는 것을 확인할 수 있다.

 

 - 장바구니에 담긴 제품 데이터를 저장소의 state에 변수로 관리하고 있다면 장바구니에 담긴 제품 수, 특정 카테고리 제품 리스트 등을 getters 를 정의하여 쉽게 가져올 수 있다.

// src/store.js
import {
  createStore
} from 'vuex'

const store = createStore({
  state() {
    return {
      count: 0,
      cart: [{
        product_id: 1,
        product_name: '아이폰 거치대',
        category: 'A'
      }]
    }
  },
  getters: {
    cartCount: (state) => {
      return state.cart.length;
    }
  },
  mutataions: {
    increment(state) {
      state.count++
    }
  }
})

export default store

 - Vue 컴포넌트에서 다음과 같이 저장소의 getters에 정의된 값에 접근할 수 있다.

// src/views/StoreAccess.vue
computed: {
  cartCount() {
    return this.$store.getters.cartCount
  }
}

 

Mutations

 - Vuex는 state에 정의된 변수를 직접 변경하는 것을 허용하지 않는다. 반드시 mutations를 이용해서 변경해야한다.

 - 즉, mutations는 state를 변경시키는 역할을 한다.

 - mutations는 비동기(Async) 처리가 아니라 동기(Sync) 처리를 통해 state에 정의된 변수의 변경사항을 추적할 수 있게 해준다.

 

 - 다음과 같이 mutations에 정의된 함수를 commit을 통해서 호출하는 것으로 저장소의 state에 저장된 변수의 값을 변경할 수 있다.

methods: {
  increment() {
    this.$store.commit('increment')
  }
}

 

Actions

 - actions는 mutations와 매우 유사한 역할을 한다.

 - action을 통해 mutations에 정의된 함수를 실행시킬 수 있다.

 

 - mutations가 있는데 왜 굳이 action을 통해서 mutations를 실행하는지 의문이 생길 수도 있다.

 - actions에 정의된 함수 안에서는 여러 개의 mutations를 실행시킬 수 있을 뿐만 아니라, mutations와 달리 비동기 작업이 가능하다.

 - 즉, actions에 등록된 함수는 비동기 처리 후 mutations를 커밋할 수 있어서 저장소(store)에서 비동기 처리 로직을 관리할 수 있게 해준다.

actions: {
  increment(context) {
    // 비동기 처리 로직 수행 가능
    context.commit('increment')
  }
}

 

Vuex 실무 예제

 - Vuex에 대해 실무에서 가장 많이 사용되는 예는 사용자가 로그인을 하면 사용자 정보를 Vuex의 store에 저장해서 사용한다.

 - 모든 컴포넌트에서는 사용자가 로그인 했는지 정보를 알 필요가 있다.

 

 - 사용자 계정(account) 정보를 프로젝트 전체에 걸쳐서 변경사항을 관리해야 하는 데이터를 처리할 때 매우 유용하다.

import {
  createStore
} from 'vuex'

import persistedstate from 'vuex-persistedstate'

const store = createStore({
  state() {
    return {
      user: {}
    }
  },
  mutations: {
    user(state, data) {
      state.user = data
    }
  },
  plugins: [
    persistedstate({
      paths: ['user']
    })
  ]
})

export default store

 

반응형