프로그래밍/Vue&Nuxt

Vuex : Mutation과 Action의 구분

말랑공룡 2019. 11. 18. 17:01

이 포스팅은 원글 (https://qiita.com/frost_star/items/4620957fce888150e4cc) 의 번역 포스팅입니다.

 

 

Vuex를 공부하면 Mutation과 Action의 처리 구분을 어떻게 할까, 하는 고민에 나름대로 정리해보았습니다.

 

 

Mutation과 Action의 차이


 

애초에 Mutation은 동기적 처리여야만 하며 Action은 비동기적 처리도 가능하다는 차이가 있습니다.

이것은 Mutation에서 다수의 상태 변경이 비동기적으로 수행되었을 경우 예측 불가능한 상태가 되는 것을 막기위한 의도가 있는 것 같습니다.

Action에서는 Mutation으로 commit을 행함으로써 간접적으로 상태를 변경하지만 Action을 호출하기 위한 dispatch 메소드는 Promise를 반환하기 때문에 처리의 순서를 제어하는 것이 가능합니다.

 

 

동기적 처리는 어느 쪽에 쓸까?


 

비동기적 처리는 Action에 구현하지 않으면 안되지만 동기적 처리는 어느 쪽에 구현하는게 좋을까요?

여기서 Action에게 전달된 text가 "Yes"라면 count+1, "No"라면 count-1, 그 외는 그대로인 State가 있다고 가정해봅시다.

 

new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        plus (state, num) {
            state.count += num;
        },
    },
    actions: {
        vote (context, text) {
            if (text === 'Yes') {
                context.commit('plus', 1);
            } else if (text === 'No') {
                context.commit('plus', -1);
            }
        },
    },
}

 

이렇게 Mutation은 State의 변경으로 놓아두고, Action에서 처리를 행하게끔 하는 것이 각 처리의 책임이 명확해져 괜찮아 보입니다. (애초에 문자열의 조건분기는 Component쪽에서 하는 것이 좋지만 일단 그것은 이 예시에서는 별개로 생각합시다.)

하지만 저 변경 처리가 State의 상태에 의존하는 변경이라면 Mutation에서 처리를 하고싶군요.

예를들어 0에서 9까지 카운트해서 9의 다음은 다시 0으로 돌아오게끔 하는 처리를 써봅시다.

 

new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        countup (state, num) {
            state.count = (state.count + num) % 10;
        },
    },
    actions: {
        increment (context) {
            context.commit('countup', 1);
        },
    },
}

 

state를 직접적으로 참조하는 것은 가능한 Mutation의 내부에서 행해지도록 하고싶습니다.

 

 

Component에서 직접 Mutation을 Commit?


 

 

Vuex는 공식적으로 Component로부터 Mutation을 직접 commit하는 것을 허가하고 있습니다.

 

단지 이 그림에는 Component로부터 Mutation을 직접 commit하는 루트가 없네요.

아마도 Component로부터의 조작은 Action에 한정시키고 싶은 의도가 있었다고 생각합니다.

단지, 공식적으로 Mutation을 직접 commit하는 것을 허가한 이유로써는 단순한 상태 조작을 만드는 상황인 경우 코드가 장황해져서(commit하는 것 뿐인 Action이 어지럽게 행해짐) 이것이 허가되지 않았을까 생각합니다.

그러므로 가능하다면 Action경유로 호출하는 편이 좋다고 생각합니다. 

 

 

mutation-types.js


 

 

Component에 대해 공개하는 것을 Action에 한정하는 생각을 넓혀나가보면, mutation-types.js(Mutation의 타입을 정수화하여 외부로 내보내기 위한 js)는 action-types.js를 하는 것이 좋지 않을까 생각합니다.

 

결론


 

 

언제까지나 개인적인 의견입니다.

 

  • Mutation은 상태(state)의 변경 시(private한(오직 Action으로부터 호출되는) Setter)
  • Action은 공개적 처리나 복잡한 처리를 행할 때(public한 method)

 

참고


Vuex 公式