Vuex의 액션(Actions)은 변이(Mutations)와 많이 비슷합니다.
변이(Mutations)는 동기적, 액션(Actions)은 비동기적 으로 작업이 처리되고 그렇게 구분해야 합니다.
변이(Mutations)는 상태(State)의 관리에 초점을 두고 있는데, 비동기 작업이 포함되면 각 컴포넌트에서 변이가 작동할 때 프로그램 흐름을 추적하기가 굉장히 어려워 집니다.
따라서 액션(Actions)을 만들어 비동기 작업 등을 구분해야 합니다.
하지만 동기와 비동기 처리를 구분해야 하는 상황이 아니라면 변이와 액션의 차이 필요성을 느끼지 못할 수 있습니다.
일단 이해를 위해 단순한 비동기 처리 할인 버튼을 만들어 보겠습니다.
먼저 변이와 액션의 차이점을 좀 더 쉽게 이해하기 위해서 Vue.js devtools를 설치하겠습니다.
Vue.js devtools는 Vue.js를 사용하는 응용 프로그램 디버깅을 위한 Chrome 및 Firefox 확장 프로그램입니다.
설치가 완료된 후 앱을 한 번 리부트합니다.
$ npm run dev
개발자 도구를 켜면 상단에 다음과 같이 ‘Vue’ 탭이 생기고 디버깅이 가능합니다.
현재 앱에서 사용하는 컴포넌트들을 확인할 수 있는 ‘Switch to Components’ 탭이 있고,
Vuex에서 발생하는 동작들을 확인할 수 있는 ‘Switch to Vuex’ 탭도 있습니다.
설치가 완료되었다면, 비동기 처리를 위해 할인(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)에서 비동기 처리를 이용하면 추적이 어렵습니다.
그래서 비동기 처리는 액션(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
를 콘솔에서 확인해 보면 다음과 같습니다.
특히 commit
을 여러 번 호출할 경우 다음과 같이 수정할 수 있습니다.
// store.js
// ...
actions: {
discountPrice({ commit }, payload) { // ES6 - Destructuring
setTimeout(() => {
commit('discountPrice', payload);
}, 2000);
}
}
// ...