일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 프론트엔드
- react
- 블록체인
- 자바스크립트
- 솔리디티
- BFS
- JavaScript
- es6
- 알고리즘
- next.js
- VUE
- k8s
- 웹
- 클라우드
- 이더리움
- 백엔드
- docker
- 컴퓨터공학
- 백준
- 가상화
- kubernetes
- 리액트
- CSS
- HTML
- TypeScript
- AWS
- 파이썬
- 쿠버네티스
- 타입스크립트
- 이슈
- Today
- Total
즐겁게, 코드
Vuex의 namespaced module 활용하기 본문
어플리케이션의 규모가 커지면 인증 정보, 장바구니 목록, 어플리케이션 설정 등 전역으로 관리해야 할 요소의 성격이 완전히 다른 경우가 종종 생기는데요, React
와 redux
를 사용할 때는 이처럼 둘 이상의 관심사가 있을 때 여러 스토어를 만들고 combineReducers
함수를 사용해 스토어를 하나로 묶어 사용했습니다.
오늘은 Vue
의 Vuex
를 사용해 스토어를 구성할 때, 관심사별로 유사한 상태를 묶어 관리할 수 있도록 해주는 네임스페이스(namespace) 에 대해 소개해보도록 하겠습니다. 🙂
네임스페이스의 등장 배경
어플리케이션이 하나의 스토어를 가질 때는 store
라는 폴더 안에 index.js
, mutations.js
, actions.js
, getters.js
라는 이름을 가진 각 파일(vuex 모듈)을 통해 전역 상태를 관리할 수 있습니다.
store
├─ index.js # 전역 상태를 관리합니다.
├─ mutations.js # 전역 상태를 동기적으로 변경하는 함수를 관리합니다.
├─ actions.js # 전역 상태를 비동기적으로 변경하는 함수를 관리합니다.
├─ getters.js # 전역 상태로부터 파생되는 값을 관리합니다.
하지만, 한 index.js
에 관심사가 다른 여러 상태가 있으면 자연스레 스토어가 복잡해지게 됩니다.
// 각각 관심사가 완전히 다른 인증(Auth), 할일 목록(Todo)의 상태입니다.
export const state = () => ({
isLoggedIn: null,
activeUser: null,
todoList: null,
selectedTodoList: null;
})
이렇게 다른 관심사를 갖는 상태를 보다 명확한 단위로 구분하기 위해 Vuex
에서는 스토어를 namespace
단위로 나누어 각 스토어의 관심사를 분리할 수 있습니다.
네임스페이스 모듈 작성하기
그럼 namespace
를 적용하면 파일 구조가 어떻게 개선될 수 있는지 확인해 보겠습니다.
아래 폴더 구조에서는 인증 정보를 관리하는 Auth
라는 폴더와, 할일 목록을 관리하는 Todo
라는 폴더를 생성한 모습입니다.
✅ 폴더의 이름이 곧 Vuex 네임스페이스가 됩니다.
store
├─ Auth
│ ├─ actions.js
│ ├─ mutations.js
│ ├─ index.js
│
├─ Todo
├─ actions.js
├─ mutations.js
├─ index.js
이제 두 스토어의 폴더가 물리적으로 분리되었으니 각 스토어의 관심사 역시 자연스럽게 분리됩니다.
보다시피 이전에는 한 state
안에 모든 전역 상태를 보관했다면, 이제는 Auth
와 Todo
의 상태를 명확히 분리할 수 있게 된 모습입니다.
// store/Auth/index.js
export const state = () => ({
isLoggedIn: null,
activeUser: null,
});
// store/Todo/index.js
export const state = () => ({
todoList: null,
selectedTodoList: null;
})
마찬가지로, mutations.js
와 actions.js
역시 동일한 방법으로 분리할 수 있게 됩니다.
// store/Todo/mutations.js
// mutations.js 에는 뮤테이션 함수를 내보냄과 동시에 정의합니다.
export const mutateTodoList = (state, updatedTodoList) => {
state.todoList = updatedTodoList;
};
🚨 반드시 주의하세요!
namespace 문법을 사용할 때는 반드시 각 모듈을 export default 가 아닌, export 로 내보내야만 합니다.
만약
export default
문으로 상태 또는 뮤테이션 등을 내보낼 시,Vuex
는 이를 올바른 모듈로 인식하지 못하여Vuex
상태에 제대로 읽고 쓸 수 없습니다.
(이는
Nuxt
2.15.8 버전에서 발생하는 이슈로, 정확히Nuxt
의 이슈인지Vuex
의 이슈인지는 파악하지 못했습니다 😢)
네임스페이스 모듈 사용하기
이제 컴포넌트 내부에서 네임스페이스 모듈을 사용하는 방법을 알아보겠습니다.
index.js
, mutations.js
, actions.js
, getters.js
모듈을 불러올 때는 map-
으로 시작하는 헬퍼 함수를 사용할 수 있는데요, 한번 아래 코드를 예시로 살펴보겠습니다.
computed: {
// mapState 함수는 computed 내부에서 스프레드 연산자와 함께 사용합니다.
// Ex- ...mapState('네임스페이스 이름', ['사용할 상태명']);
...mapState('Todo', ['todoList']);
// 둘 이상의 상태도 불러올 수 있습니다.
...mapState('Auth', ['isLoggedIn', 'activeUser']);
// mapGetters의 사용 방법 역시 동일합니다.
}
methods: {
// mapMutations 함수는 methods 내부에서 스프레드 연산자와 함께 사용합니다.
// Ex- ...mapMutations('네임스페이스 이름', ['사용할 뮤테이션 명']);
...mapMutations('Todo', ['mutateTodoList']);
// 둘 이상의 뮤테이션 함수도 불러올 수 있습니다.
...mapMutations('Auth', ['signIn', 'signOut']);
// mapActions의 사용 방법 역시 동일합니다.
}
이제 map-
헬퍼를 통해 어떤 네임스페이스의 상태를 가져오거나 조작할지 보다 명확하게 나타낼 수 있게 되었습니다.
간단한 실제 적용 사례
제가 작업하고 있는 프로젝트 중, mapState
와 mapMutations
를 불러와 사용하는 유스케이스입니다.
<template>
<Home />
</template>
<script>
import getLocalANSData from "@/apis/ANSData/getLocalANSData";
import { mapMutations, mapState } from "vuex";
export default {
name: "MainPage",
components: {
Home: () => import("@/components/pages/home"),
},
async mounted() {
const { data } = await getLocalANSData();
this.initData(data);
},
computed: {
...mapState("Auth", ["activeUser"]);
},
methods: {
...mapMutations("ansData", ["mutateANSData"]),
initData(data) {
this.mutateANSData(data);
},
},
};
</script>
오늘 다룬 네임스페이스 문법이 코드 개선에 도움이 되시길 바라며, 다음에는 더 나은 글로 찾아뵙도록 하겠습니다. 🙂
'🎨 프론트엔드 > Vue.js' 카테고리의 다른 글
vee-validate에 타입스크립트 적용하기 (@vee-validate/yup) (0) | 2024.12.19 |
---|---|
[Vue] inject-provide 패턴 조금 더 잘 써보기 (0) | 2024.11.19 |
Vue 3에서 페이지 전환 애니메이션 추가하기 (0) | 2023.12.24 |
v-show와 v-if 지시자의 차이 (0) | 2021.08.18 |
Vue 컴포넌트에서 name 속성을 명시하는 이유 (0) | 2021.05.24 |