본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section15] 224. 네임스페이스 모듈

# 지역 모듈

지역 상태 외에도, 모듈 전체를 지역 모듈로 만들 수 있다.
어떻게?
→ 바로 namespace를 이용해서.
여러 모듈을 분명하게 서로 분리하기 위해서.
 
 

# 지역 모듈을 사용하는 경우

그렇다면 지역모듈은 어떤 경우에 사용할까?
→ 애플리케이션이 커지면서 이름이 중복되는 경우가 생긴다.
한 저장소 내에 다른 모듈의 getter나 actions 등에 같은 이름을 사용하게 될 수도 있다.
 
예를 들어, 만약 counterModule에 login 액션이 있다면, 메인 저장소에 있는 login 액션과 충돌한다.
현재, state를 제외하고 모든 것이 하나의 객체로 결합된 상태이므로.

// main.js
const counterModule = {
  actions: {
    login(){}, // login액션 추가 시, 아래 메인저장소의 login 액션과 충돌
  },
};

const store = createStore({
  actions: {
    login(context) {
      context.commit('setAuth', { isAuth: true });
    },
  },
});
// 생략..

 
 

# 지역 모듈로 만드는 방법

앱이 커지면서 이런 충돌이 일어날 가능성을 모듈에 namespace를 사용하여 방지할 수 있다.
→ 객체 안에 추가 옵션으로 namedspaced를 true로 설정해라.

// main.js
const counterModule = {
  namespaced: true,
  actions: {
    login(){}, // login추가. 아래 메인저장소의 login 액션과 충돌
  },
};

const store = createStore({
  actions: {
    login(context) {
      context.commit('setAuth', { isAuth: true });
    },
  },
});
// 생략..

 
이렇게 namespace를 true로 설정하면 상태 뿐만 아니라 모듈 전체가 저장소로부터 분리되어야 한다는걸 Vuex에 알리게 된다.
 
 
 

# namespace사용 시, getter와 actions 사용방법

하지만 이렇게 하면 getter와 actions 디스패치가 더이상 작동하지 않는다.
해당 액션 및 게터를 메인 저장소에서 사용할 수 없게 된 것.

 
이제 알맞은 namespace를 통해 액세스해야한다.
 
 
그럼 네임스페이스는 무엇이며, 어떤 원리로 작동할까?
네임스페이스는 store의 modules에 모듈을 추가할 때 지정하는 키이다.
아래의 경우, 'numbers'가 counterModule의 네임스페이스이다.

const store = createStore({
  modules: {
    numbers: counterModule,
  },
  //생략
}),

이제 이 네임스페이스를 이용해 모듈 내 액션과 게터 등을 다뤄야한다.
 
 

## getters 사용 시

이전에는 FavoriteValue.vue에서 getters.normalizedCounter로 액세스 했었다.

<!--FavoriteValue.vue-->
<template>
  <h3>{{ counter }}</h3>
  <p>We do more...</p>
</template>
<script>
export default {
  computed: {
    counter() {
      return this.$store.getters.normalizedCounter;
    },
  },
};
</script>
// main.js
const counterModule = {
  namespaced: true,
  state() {
    return {
      counter: 0,
    };
  },
  mutations: {
    increment(state) {
      state.counter = state.counter + 2;
    },
    increase(state, payload) {
      console.log('state', state);
      state.counter = state.counter + payload.value;
    },
  },
  actions: {
    increment(context) {
      setTimeout(function () {
        context.commit('increment');
      }, 2000);
    },
    increase(context, payload) {
      console.log('context', context);
      context.commit('increase', payload);
    },
  },
  getters: {
    // 생략..
    normalizedCounter(state) {
      const finalCounter = state.counter * 3;
      if (finalCounter < 0) {
        return 0;
      }
      if (finalCounter > 100) {
        return 100;
      }
      return finalCounter;
    },
  },
};

 
 
이제 .normalizedCounter로 액세스 하는게 아니라, 특수 기호를 포함한 특수 프로퍼티 이름을 대괄호 안에 입력해 액세스해야한다.
대괄호 안에 프로퍼티 이름을 문자열로 전달하는데, 이 때 프로퍼티 이름인 'normalizedCounter' 앞에 네임스페이스인 'numbers' + '/'(슬래시)를 입력한다.

<!--FavoriteValue.vue-->
<template>
  <h3>{{ counter }}</h3>
  <p>We do more...</p>
</template>
<script>
export default {
  computed: {
    counter() {
      return this.$store.getters['numbers/normalizedCounter'];
    },
  },
};
</script>

 
이렇게 '네임스페이스/게터 및 액션 이름' 이렇게 입력한다. 위 경우는 게터이다.
 
이제 counter가 보인다.

 
 

## mapGetters 사용 시

mapGetters를 사용할 시, 첫번째 인수로 네임스페이스를 전달해라. 그리고 뒤에는 전처럼 게터 이름으로 배열을 추가한다.

<!--TheCounter.vue-->
<template>
  <h3>{{ finalCounter }}</h3>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
  computed: {
   // 생략..
    ...mapGetters('numbers', ['finalCounter']),
  },
};
</script>

 
 
저장해보면 두 번째 카운터도 다시 돌아왔다.

 
즉, mapGetters를 사용할 때는
첫 번째 인수는 네임스페이스, 두 번째 인수는 네임스페이스 내 게터의 배열이다.
 
 

## mapActions 사용 시

ChangeCounter.vue에서 mapActions의 첫 번째 인수로 네임스페이스를 추가하고,
전과 똑같이 액션 이름을 추가한다.

<template>
  <button @click="inc">Add 2</button>
  <button @click="increase({ value: 11 })">Add 11</button>
</template>
<script>
import { mapActions } from 'vuex';
export default {
  methods: {
    ...mapActions('numbers', { inc: 'increment', increase: 'increase' }),
  },
};
</script>

 
 
또 App.vue의 dispatch에서 type으로 increase 앞에 numbers/를 붙여보자.

// App.vue
methods: {
  addOne() {
    this.$store.dispatch({
      type: 'numbers/increase',
      value: 10,
    });
  },
},

 
기억해두자.
네임스페이스/액션이름
 
 
그러면 모든 버튼이 정상적으로 작동한다.
이렇게 네임스페이스 기능을 사용하여 모듈을 분리시켜 이름이 충돌하지 않도록 만들었다.
지금은 이름충돌이 없지만, 앱이 커지면 생길 수 있는 일이다.
 
 
** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.