woolta

module registration 패턴 으로 vuex 모듈 관리하기

wooltaUserImgb00032 | vue | 2019-04-17

VUEX MODULE

상용 프로그램을 vuex로 상태관리를 하게 되면 각각의 action, getter, mutaion, state 단일 파일로는 관리가 힘들기 때문에 역활에 맞도록 모듈화 하여 아래와 같이 유지보수 하게 됩니다.

store directory 구성

https://image.woolta.com/3fcd28f4384144e4.png

store

// store/index.js

import Vue from 'vue';
import Vuex from "vuex";
import item from './modules/item';
import user from './modules/user';
import list from './modules/list';

Vue.use(Vuex);

export const store = new Vuex.Store({
    modules: {
        item,
        user,
        list
    }
});

module example

// store/modules/item.js

import { fetchList } from "../../api/listAPI";
// state
export const state =  {
    list: [],
};

// mutations
export const mutations = {
    SET_LIST(state, data) {
        state.list = data;
    }
};

//getters
export const getters = {}

//actions
export const actions = {
    async FETCH_LIST({commit}, pageName){
        const res = await fetchList(pageName);
        commit("SET_LIST", res.data);
        return res;
    },
};

위와 같이 Store 를 구성할 경우 유저에 대한 상태를 변경 or 확인 해야 하는 경우 item모듈 을 바로 확인하고 유지보수 하면 되므로 직관적으로 유지보수 가능한 장점이 있습니다.

Store index.js 개선 포인트

위에 있는 Store index.js 를 보게 되면 모든 모듈들을 import 하여 vuexStore 에 넣어주는 모습을 볼 수 있습니다. 그러나 이때 모듈들이 추가 되게 된다면 그때마다 추가된 모듈Store index.js 에 넣어주어야 합니다. 물론 별로 힘든 작업은 아니지만 단순히 추가된 모듈 파일만 추가로 import 시키는 단순 반복 작업이므로 이를 개선 시켜 보도록 하겠습니다.

require.context

위의 기능 개선을 위한 핵심 함수 입니다. require.contextwebpack 에서 지원하는 기능 으로 파라미터 조건에 맞는 모든 파일을 로드 시켜줍니다. 파라미터는 총 3가지 로 역활은 다음과 같습니다.

require.context(
    directory,  // 검색 폴더 위치
    useSubdirectories, // 1번 파라미터인 검색폴더 의 하위 폴더까지 전부 로드 할지 유무
    regExp // 파일 검색 정규 표현식
);

module registration 패턴 을 사용한 개선

store 모듈 개선해보기

우선 위에서 설명한 require.context 를 사용해 module 폴더 에 있는 파일들을 로드시켜 보도록 하겠습니다.

  • 우선 Module 폴더에 index.js 파일을 생성합니다.

module index.js 작성

// store/modules/index.js

import camelCase from 'lodash/camelCase';

// module 폴더(.)에 있는 모든 js 파일 로드, 하위폴더는 없으므로 false.
const requireModule = require.context('.',false, /\.js$/);

const modules = {};

requireModule.keys().forEach(filename => {
    // module 폴더에 index.js 는 로드 파일이 아니므로 제외
    const isIndexJsFile = filename ===  './index.js';
    
    if(!isIndexJsFile){
        // 모듈 네임 camelCase 치환 
        const moduleName = camelCase(filename.replace(/(\.\/|\.js)/g,''));
        // 모듈 추가 
        modules[moduleName] = requireModule(filename); 
    }


});

export default modules;

위의 작업에서 modules 안에 하위 폴더가 필요한 경우는 require.context 의 2번째 파라미터를 true 로 허용 한 후 추가 처리 해주시면 됩니다.

module nameSpaced 설정

vuex로 모듈 설정시 nameSpaced 옵션을 사용할 경우가 대다수 인데 그럴 경우는 다음과 같이 세팅해주시면 됩니다.( 모듈에서 추가하는게 아닌 위의 index.js에서 해주시면 됩니다.

import camelCase from 'lodash/camelCase';

// module 폴더(.)에 있는 모든 js 파일 로드, 하위폴더는 없으므로 false.
const requireModule = require.context('.',false, /\.js$/);

const modules = {};

requireModule.keys().forEach(filename => {
    // module 폴더에 index.js 는 로드 파일이 아니므로 제외
    const isIndexJsFile = filename ===  './index.js';
    
    if(!isIndexJsFile){
        // 모듈 네임 camelCase 치환 
        const moduleName = camelCase(filename.replace(/(\.\/|\.js)/g,''));
        // 모듈 추가 (namespaced 설정)
        modules[moduleName] = {namespaced:true, ...requireModule(filename)};
    }


});

export default modules;

위와 같이 설정 한다면 실제 Store 파일 에서는 해당 index.js 만 Import 하게 되면 파일이 얼마든지 추가 되어도 따로 Import 시켜주지 않아도 자동으로 추가 될 수 있습니다.

개선 후 store index.js

import Vue from 'vue';
import Vuex from "vuex";
import modules from './modules';

Vue.use(Vuex);

export const store = new Vuex.Store({
    modules
});

위의 코드처럼 단순히 초기 한번만 세팅 하고 더이상 변경할 필요가 없습니다. 이때 index.js 까지 import를 안한 이유는 폴더까지만 import 경로로 지정하면 자동으로 index.js 로 추가하기 때문입니다.

위와 같이 구성하게 되면 비록 파일 하나 추가 안하는 정도 이지만 생각보다 귀찮은 작업을 많이 없앨 수 있습니다. 또한 비슷한케이스에 해당 작업을 응용해서 변경하실 수 있습니다.

Copyright © 2018 woolta.com

gommpo111@gmail.com