Vuex에 대해서
💡 Vuex는 Vue.js에서 사용하는 상태 관리 저장소 라이브러리입니다. 모든 Vue Component에서 접근 가능한 이 상태 관리 저장소는 모든 데이터의 흐름을 중앙에서 관리할 수 있다는 편리함을 제공하는데요, 오늘은 이 Vuex의 흐름과 규칙에 대해서 정리해보도록 하겠습니다.
Vuex의 기본 흐름
Vuex를 검색하면 가장 먼저 나오는 이 흐름도를 많이 접하셨을 것같아요. 그런데 저는 처음에 이 그림이 도통 이해가 안가더라구요..😅 제가 이해한 내용을 바탕으로 최대한 이해하기 쉽게 설명드리겠습니다!

일단 크게 이 3가지만 알고 계시면 됩니다!
- State(상태)
- Mutation(변이)
- Actions(액션)
State(상태)
각각의 Component에서 필요한 데이터를 꺼내다 쓸 수 있어야겠죠? 그런데 우리 개발해보면 느끼셨을지 모르겠지만, 원본데이터를 유지하는게 중요하잖아요. 그 원본 데이터가 바로 State입니다!
const store = new Vuex.Store({
state: {
count: 0;
}
});
우리 그러면 State를 Component로 가져다가 사용하는 법도 알아야겠죠?
아주 간단합니당! computed에서 가져다가 사용하면 됩니다.
형식은 this.$store.state.stateName
다음처럼 작성해주시면 됩니다!
그러면 State 값에 변화가 있을 때마다 computed에서 자동으로 계산이 되어서 변경된 값으로 화면에 출력이 될 것입니다. 너무 좋죠?
export default {
computed: {
count() {
return this.$store.state.count;
}
}
}
Mutation(변이)
제가 Vuex를 처음 접할 때 가장 어렵고 이해하기 어려웠던 것이 Mutation이에요. 제대로 사용 못해서 이전에 작성했던 코드를 보면 엉망인 부분도 있답니다..😅 볼때마다 부끄러워서 얼른 수정해야겠어요!
Mutation(변이)는 Vuex 스토어에서 State를 변경할 수 있는 유일한 방법입니다.
위에서 설명했듯이 State는 원본 데이터라고 했죠? 이 데이터를 바꿔줄 수 있는 유일한 아이가 바로 이 Mutation(변이)입니다!
이 방법 외에 값을 자체적으로 바꿀 수도 있지만 좋지 않은 방법이고 규칙을 무시하는거라서 웬만하면 Mutation(변이)를 이용해서 수정해보도록 합시다!
Redux의 Reducer가 비슷한 역할을 한다고 생각해요.
const store = new Vuex.Store({
state: {
count: 0;
},
mutation: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
}
});
우리 그러면 Mutation을 Component로 가져다가 사용하는 법도 알아봐요!
Mutation은 State와는 다르게 직접 호출하지 않고 commit 메소드를 사용합니다.
this.$store.commit('Mutation 메소드 명')
처럼요!
왜 commit이냐?
commit
이라는 용어는 변경을 확정한다는 뜻입니다.
저희 git을 사용할 때 저장소에 변경된 내용을 commit
하잖아요? 그거랑 연관지어 생각해보면 이해가 확 되지않나요? 히히 :)
<template>
<div>
<button @click="store.commit('increment')">증가</button>
<button @click="store.commit('decrement')">감소</button>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count;
}
}
}
</script>
🚨 주의
Mutation(변이)핸들러 함수
는 반드시 동기적 이어야 합니다! 그러면 비동기처리는 어디서 하느냐? 바로 다음Actions
에서 살펴봅시다!
Actions(액션)
저는 처음에 이 Actions(액션)을 사용해서 State를 변경시키는 것! 이라고 생각을 했었어요. 그런데 Actions는 모든 과정이 끝났을 때 Mutation(변이)에 대한 commit
을 진행하는 것이래요.
아까 우리 commit
이 뭐라고 했죠?! 변경 내용을 확정시키는 일!!!
그래서 Actions에서 모든 비동기 처리를 마치고 그 결과를 Mutation(변이)로 commit
을 해서 Vuex 스토어의 데이터를 업데이트 시켜줍니다.
const state = {
...
user: {
loggedIn: false,
data: {}
}
}
...
const mutations = {
...
SET_USER(state, data) {
state.user.data = data
}
}
...
const actions = {
fetchUser({ commit }, user) {
if (user) {
this.state.uid = user.uid;
axios.get('/api/read/' + user.uid)
.then(async response => {
await commit("SET_USER", {
uid: user.uid,
phoneNumber: user.phoneNumber,
displayName: response.data.displayName,
email: response.data.email,
})
})
} else {
commit("SET_USER", null);
}
},
}
다음 코드는 제가 작업을 진행했던 코드로, 사용자의 정보가 있다면 payload를 가진 SET_USER라는 mutations에 대한 commit을 진행한 것입니다.
payload 란?
그냥 단순하게commit
에서 전달된 매개변수 입니다.
대부분의 payload
는 여러 필드를 포함할 수 있는 객체(Object) 형태로 전달이 됩니다.
Getters(게터)
우리 이제 Vuex의 3가지 컨셉에 대해서는 모두 살펴보았습니다! 👏👏👏 그런데 아직 하나 더 남았어용..ㅎㅎ 마지막으로 Getters(게터)입니다.
Getters(게터)는 단순하게 Component에서 본 computed 속성과 같은 역할을 합니다. State를 직접 사용하는 것이 아닌, State를 이용해서 계산된 속성을 가져다가 사용하는 것이죠! 이러면 자연스럽게 State 값이 변경되면 변경된 계산 결과 값을 가질 수 있을거에요!
const store = new Vuex.Store({
...
getters: {
duckCount(state) {
return state.ducks.length;
}
}
});
Vuex의 장점
애플리케이션에서 사용하고 있는 데이터의 흐름을 추적 하기가 매우 직관적이고 편리하다는 것! 언제 어떤 데이터가 변이되었는지를 확인할 수 있었잖아요! 그래서 이걸 시간여행 디버깅이라고도 한대요ㅎㅎ 표현이 너무 귀엽죠?? :)