HEROPY
Tech
{{ scrollPercentage }}%

Vuex - 5 - Actions / Context / Vue.js Devtools

js vue vuex

Vuex Actions

Vuex의 액션(Actions)은 변이(Mutations)와 많이 비슷합니다.
변이(Mutations)는 동기적, 액션(Actions)은 비동기적 으로 작업이 처리되고 그렇게 구분해야 합니다.

변이(Mutations)는 상태(State)의 관리에 초점을 두고 있는데, 비동기 작업이 포함되면 각 컴포넌트에서 변이가 작동할 때 프로그램 흐름을 추적하기가 굉장히 어려워 집니다.
따라서 액션(Actions)을 만들어 비동기 작업 등을 구분해야 합니다.

하지만 동기와 비동기 처리를 구분해야 하는 상황이 아니라면 변이와 액션의 차이 필요성을 느끼지 못할 수 있습니다.
일단 이해를 위해 단순한 비동기 처리 할인 버튼을 만들어 보겠습니다.

먼저 변이와 액션의 차이점을 좀 더 쉽게 이해하기 위해서 Vue.js devtools를 설치하겠습니다.

Vue.js devtools

Vue.js devtools는 Vue.js를 사용하는 응용 프로그램 디버깅을 위한 Chrome 및 Firefox 확장 프로그램입니다.

설치가 완료된 후 앱을 한 번 리부트합니다.

$ npm run dev

개발자 도구를 켜면 상단에 다음과 같이 ‘Vue’ 탭이 생기고 디버깅이 가능합니다.

현재 앱에서 사용하는 컴포넌트들을 확인할 수 있는 ‘Switch to Components’ 탭이 있고,

Vue.js devtools

Vuex에서 발생하는 동작들을 확인할 수 있는 ‘Switch to Vuex’ 탭도 있습니다.

Vue.js devtools

설치가 완료되었다면, 비동기 처리를 위해 할인(Discount Price) 버튼을 클릭하여 2초 후 할인이 적용되도록 코드를 수정하겠습니다.

// store.js
// ...

export const store = new Vuex.Store({
  state: {
    // ...
  },
  getters: {
    // ...
  },
  mutations: {
    discountPrice(state, payload) {
      setTimeout(() => {
        state.fruits.forEach(fruit => {
          fruit.price *= (100 - payload.discountRate) / 100;
        });
      }, 2000);
    }
  }
});

이제 버튼을 눌러보세요.
버튼을 누를 때마다 개발자 도구 ‘Vue.js devtools’ 패널에 discountPrice 변이가 즉시 기록되지만, 실제로 화면에 할인된 가격이 적용되는 변화는 2초 후 일어납니다.
이렇게 변이(Mutations)에서 비동기 처리를 이용하면 추적이 어렵습니다.

Async Mutations

그래서 비동기 처리는 액션(Actions)으로 작성해야 합니다.
다음과 같이 actions 속성을 추가하고 discountPrice 액션을 만들어 줍니다.
비동기 처리를 위해 setTimeout 함수를 실행하고 내부에서 commit으로 변이를 호출합니다.
당연히 discountPrice 변이에서는 비동기 처리를 제거합니다.

// store.js
// ...

export const store = new Vuex.Store({
  state: {
    // ...
  },
  getters: {
    // ...
  },
  mutations: {
    discountPrice(state, payload) {
      state.fruits.forEach(fruit => {
        fruit.price *= (100 - payload.discountRate) / 100;
      });
    }
  },
  actions: {
    discountPrice(context, payload) {
      setTimeout(() => {
        context.commit('discountPrice', payload);
      }, 2000);
    }
  }
});

변이(Mutations)를 호출하기 위해서는 commit 메소드를 사용했습니다.
하지만 액션(Actions)을 호출하기 위해서는 dispatch 메소드를 사용해야 합니다.

<!--BtnDiscount.vue-->
<!-- ... -->

<script>
  export default {
    methods: {
      discountPrice() {
        // 액션 호출
        this.$store.dispatch('discountPrice', {
          discountRate: 20
        });
      }
    }
  }
</script>

<!-- ... -->

자 이제 비동기 처리를 변이에서 액션으로 옮겼으니 실제로 동작시켜 봅시다.
버튼을 눌러보면 ‘Vue.js devtools’ 패널에 discountPrice 변이가 즉시 표시되지 않고, 2초 후 표시됩니다.
즉, 비동기 처리는 액션(Actions)으로 관리해야 추적이 가능하단 부분이죠.

추가로 actions의 메소드는 context라는 인자를 갖는데, 이는 저장소(Store)의 state, getters, commit 등에 접근할 수 있습니다.
context를 콘솔에서 확인해 보면 다음과 같습니다.

Context in Actions

특히 commit을 여러 번 호출할 경우 다음과 같이 수정할 수 있습니다.

// store.js
// ...
actions: {
  discountPrice({ commit }, payload) {  // ES6 - Destructuring
    setTimeout(() => {
      commit('discountPrice', payload);
    }, 2000);
  }
}
// ...