devlog,

Vuex 리펙토링

FreeVue FreeVue Follow Jul 10, 2019 · 5 mins read
Vuex 리펙토링
Share this

이전 글에 디렉터리 구성을 소개했습니다. 이번에는 Vuex 구성 소스들을 소개하겠습니다.

이전에는 Vuex의 actions기능을 사용하는 일이 없었습니다. 그냥 바로 각 파일들에서 이벤트가 진행되고 필요하면 Vuex의 mutations을 직접 호출하여 변이를 시키는 방식으로 작업을 했습니다.

하지만 시간이 지날수록 이 방법의 관리가 힘들어지기 시작했습니다. 그래서 containers라는 폴더구성을 만들고 components에게 props를 해주는 기능을 담기 시작했습니다. 물론 state는 Vuex를 활용하기 시작했습니다.

그런데 모든 페이지 기능들을 하나의 Vuex파일에 담기에는 어려움이 있었습니다. 그래서 각각 모듈 파일을 나누어 불러오는 방식을 선택했습니다.

여기서 구성이 마무리 되었으면 했지만 한가지 걸리는 점이 더 있었습니다. Vuex를 모듈로 나누어 각각의 파일로 관리를 하니 메소드의 이름들을 고유의 값으로 만들기가 어려웠습니다. 결국 명령어를 담는 파일을 하나 더 만들어서 각각의 맞는 부분으로 분산하여 뿌려주기로 했습니다.

store/Constant.js
export const SystemConst = {
  $Set: {
    Agent: 'SET/SYSTEM/ENV',
  },
  $Get: {
    Agent: 'GET/SYSTEM/ENV',
  },
  $Call: {
    Agent: 'CALL/SYSTEM/ENV',
  },
}

export const AuthConst = {
  $Set: {
    Auth: 'SET/AUTH/AUTH',
  },
  $Get: {
    Auth: 'GET/AUTH/AUTH',
  },
  $Call: {
    Login: 'CALL/AUTH/LOGIN',
  },
}
store/System.js
import {SystemConst} from './Constant'

export default {
  state: {
    uAgent: '',
  },
  mutations: {
    [SystemConst.$Set.Agent]: (state, payload) => {
      state.uAgent = payload
    },
  },
  getters: {
    [SystemConst.$Get.Agent]: (state) => state.uAgent,
  },
  actions: {
    [SystemConst.$Call.Agent]: (store, model) =>
      new Promise((resolve) => {
        store.commit(SystemConst.$Set.Agent, model)

        return resolve()
      }),
  },
}
store/Auth.js
import {Auth} from 'axios'
import {AuthConst} from './Constant'

export default {
  state: {
    auth: false,
  },
  mutations: {
    [AuthConst.$Set.Auth]: (state, payload) => {
      state.auth = payload
    },
  },
  getters: {
    [AuthConst.$Get.Auth]: (state) => state.auth,
  },
  actions: {
    [AuthConst.$Call.Login]: (state, model) =>
      new Promise(async (resolve, reject) => {
        try {
          const {data} = await Auth.postLogin(model)

          return resolve(data)
        } catch (e) {
          console.error('AuthConst.$Call.Login Error')

          return reject(e)
        }
      }),
  },
}
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import System from './System'
import Auth from './Auth'

Vue.use(Vuex)

export default new Vuex.store({
  modules: {
    System,
    Auth,
  },
})

모든 API통신과 state의 변이는 Vuex에서만 일어나게 만들었습니다. 그러면 각각의 페이지나 파일에서는 명령어를 호출만 하게됩니다.

src/App.vue
<template>
  <div>
    <p></p>
  </div>
</template>

<script>
import {mapGetters} from 'vuex'
import {SystemConst, AuthConst} from '@/store/Constant'

export default {
  name: 'App',
  computed: {
    ...mapGetters({
      agent: SystemConst.$Get.Agent,
      auth: AuthConst.$Get.Auth,
    }),
  },
  methods: {
    async _Login() {
      try {
        await this.$store.dispatch(AuthConst.$Call.Login)
      } catch (e) {
        console.error(e)
      }
    },
  },
  created() {
    if (!this.auth) this._Login()
  },
}
</script>

단순히 페이지에서는 dispatch하나로 API를 통신하고 Vuex를 변이시키면서 에러대응만 확인하는 간단한 소스가 되었습니다.

에러가 발생시 직관적으로 해당 메소드에서 대응이 가능하고, 버그가 발생하면 해당 Vuex의 actions만 확인하면 되어 관리포인트 또한 두곳으로 간단해졌습니다.

결과 이미지 1