vue.js를 사용하다 보면 전역적으로 사용되는 것들이 있다. vuex는 이러한 것들을 쉽게 사용하게 해주는 상태관리 라이브러리이다.
먼저 프로젝트를 생성하고 vuex를 설치하도록 하자.
vue add vuex
해당 내용을 입력하면 vuex를 설치할 수 있다.
vuex를 설치하면 store/index.js 파일이 생성된다.
vue 2.0 버전
vue 3.0 버전
main.js에 store가 등록이 되어 전역으로 사용이 가능해진다.
store의 index.js 파일에 state 위치에 count를 선언하였다.
state는 컴포넌트의 속성 data와 비슷하다고 생각할 수 있을 것 같다.
이 counter의 값을 변경하는 ControllerView와 값을 출력만 하는 PanelView를 통하여 vuex를 활용해 보겠다.
App.vue
<template>
<div id="app">
<PanelViewVue></PanelViewVue>
<ControllerViewVue></ControllerViewVue>
</div>
</template>
<script>
import PanelViewVue from "./views/PanelView.vue";
import ControllerViewVue from "./views/ControllerView.vue";
export default {
name: "App",
components: {
ControllerViewVue,
PanelViewVue,
}
};
</script>
<style>
#app {
text-align: center;
margin-top: 60px;
}
</style>
PanelView.vue
<template>
<div id="panel">현재 카운터의 값 : {{ count }}</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count; // store의 count값을 가져옴.
},
},
};
</script>
<style scoped>
#panel {
margin-bottom: 20px;
border: 1px solid black;
}
</style>
ControllerView.vue
<template>
<div id="controller">
<button @click="increase">증가</button>
<button @click="decrease" style="margin-left: 10px">감소</button>
</div>
</template>
<script>
export default {
methods: {
increase() {
this.$store.state.count++; // store에 있는 값을 증가 시켜준다.
},
decrease() {
this.$store.state.count--; // store에 있는 값을 감소 시켜준다.
},
},
};
</script>
<style scoped>
#controller {
border: 1px solid red;
}
</style>
PanelView는 검은 테두리, ControllerView는 빨간 테두리이다.
먼저 controllerView를 확인해보자.
increase와 decrease 함수를 호출할때 count의 값이 증가한다.
다만 위의 예제는 좋은 예제는 아니다. state의 값을 바로 변경하는 점은 좋은 방법이 아니다. state의 값은 mutations라는 것을 통하여 변경해야 한다. 이번에는 예제를 위하여 이렇게 작성했을 뿐이다.
count의 값을 위처럼 보여줄 수 있다.
위의 내용은 mapState를 활용한 내용이다. 이러한 방식으로도 선언이 가능하다.
getters는 computed와 유사한느낌이라고 할 수 있다.
state에 있는 내용을 한번 감싸서 내보내는 개념이라고 보면 될 것 같다.
이렇게 구현하는데 특이한 점은 this.count 가 아닌 state라는 paramter를 받아서 state의 값을 가져올 수 있다는 점이다.
이렇게 앞에 0이 붙는 포맷이 만들어졌다.
getters도 마찬가지로 mapGetters를 이용하여 사용이 가능하다.
mutations는 state를 변경하는 용도라고 생각하면 된다.
mutations는 동기방식으로 state를 처리해야한다.
mutations에 선언한 내용을 호출하는 방법이다. commit을 통하여 호출이 가능하다.
마찬가지로 mutations도 이렇게 사용할 수 있다.
actions는 비동기처리를 할 수 있으며, mutations를 commit 가능하다.
위의 형태로 사용이 가능하다.
위의 형태로 사용이 가능하다. dispatch를 이용하여 호출이 가능하다.
역시 mapActions를 통하여 이렇게 사용할 수 있다.
위에 설명에 분명히 mutations는 동기적인 내용을 정의하라고 하였고, actions는 비동기로 mutations를 실행시키는 형태로 사용하라고 하였다. 하지만 막상 mutations에서 비동기 함수가 실행 되지 않는건 아니다. 기능적으로는 불가능한것은 아니지만 vuex 공식홈페이지에서도 mutations는 반드시 동기적으로 써야한다고 되어있다. 그 이유는 vue devtools에서 state변화 추적이 어렵기 때문이다.
위의 예제를 보자 actions에 비동기 함수를 2개(axios와 setTimeout) 선언하였다.
그리고 ControllerView.vue에서 API 호출 버튼을 만든다.
그리고 PanelView.vue에서 출력한다.
해당 내용은 vue devtools이다. 크롬 extensions에서 설치 가능하다. edge에도 존재한다. 위에서 보다싶이 actions가 언제 호출 되었는지 알수가 있다. 하지만 만든 함수내에는 비동기 함수들이 있기 때문에 저기에 적힌 end는 정확한 시간이 아니다.
여기 시간을 보면 start시간과 비교하여 2초가량 느리게 나온다. 그것은 setTimeout 시간을 2초 이후로 설정했기 때문이다.
다음은 사용하지 말라고하는 mutations에 비동기 함수를 작성해보도록 하자.
(일부로 console에 시간을 찍어보았다.)
42초에 찍혔다.
console은 44초 이다.
해당 로그를 보면 mutations만으로는 언제 state가 변경되었는지 추적이 불가능 하다는 걸 알 수 있다. mutations에 비동기를 동작하면 state가 언제 바뀌는지는 알기가 어렵기 때문이다.
결론은 추적을 용이하게 vuex를 작성할때는 actions에서 로직을 처리하고 mutations는 state를 변경하는 식으로 코드를 구성해주면 추적이 용이하게 작성이 가능하다.