개선 이유
메이플스토리 월드의 포털 웹페이지는 Vuex를 사용해 상태 관리를 하고 있다. 그런데 스토어의 특정 값 갱신 시 매번 mutation, action 정의 코드를 작성하는 것이 번거로워서 공통화 코드를 작성했다. 아래 이미지와 코드를 살펴보자!
위 이미지는 현재 스토어 구조다. initialCategoryNo
을 변경하기 위해 코드를 작성한다고 가정해 보자.
AS-IS
mutation 코드 작성
1
2
3
const SET_INITIAL_CATEGORY_NO = (state, payload) => {
state.initialCategoryNo = payload
}
action 코드 작성
1
2
3
const setInitialCategoryNo = ({ commit }, payload) => {
commit('SET_INITIAL_CATEGORY_NO', payload)
}
참고로 현재 팀에서 코드 일관성을 위해 비동기 통신을 통한 스토어 값 갱신이 아니더라도 action을 작성하고 있다.
클라이언트 코드 작성 (사용 측)
1
2
3
4
5
6
7
8
export default {
methods: {
...mapActions('game', ['setInitialCategoryNo'],
mutateStoreExample() {
this.setInitialCategoryNo(1000)
}
}
}
개선점
스토어의 특정 필드를 수정할 때마다 매번 mutation과 action을 작성해야 한다. (= 보일러 플레이트 코드 발생)
TO-BE
스토어에 있는 모든 데이터를 변경할 수 있는 action과 mutation을 정의하고 재사용하도록 변경해 보자!
공통 mutation 코드 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SET_VUEX_VALUE(state, payload) {
function f(state, payload) {
const { path, value } = payload
const keys = path.split('.')
const key = keys.shift()
if (keys.length === 0) {
state[key] = value
} else {
f(state[key], { path: keys.join('.'), value })
}
}
f(state, payload)
}
재귀를 사용해 스토어 구조에서 object depth가 있는 경우에도 갱신할 수 있도록 한다.
공통 action 코드 작성
1
2
3
setVuexValue({ commit }, payload) {
commit('SET_VUEX_VALUE', payload)
}
클라이언트 코드 작성 (사용 측)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default {
methods: {
...mapActions(['setVuexValue'],
mutateStoreExample() {
this.setVuexValue({ path: 'game.initialCategoryNo', value: 1000 })
}
}
}
// setVuexValue는 재사용 가능함! 아래는 다른 Vue Component라고 가정해보자.
export default {
methods: {
...mapActions(['setVuexValue'],
mutateStoreExample() {
this.setVuexValue({ path: 'game.currentCategoryNo', value: 1000 })
}
}
}
결론
setVuexValue
를 한번 정의해 놓으면 여기저기에서 재사용할 수 있다. 이는 매번 작성되는 보일러 플레이트 코드의 상당한 부분을 줄일 수 있게 해준다. 하지만 스토어 값 갱신이 하나의 action, mutation으로 통일되면서 크롬에서 제공하는 Vue 개발자 도구에서 디버깅을 통한 데이터 추적이 불편해진다.
참고
함수형 프로그래밍 스터디에서 공부한 내용을 적용했다. 노션 링크