일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- vue.js 로그인
- React
- 컴포넌트
- vue.js
- router push
- State
- vuex
- 클래스형 컴포넌트
- 라이프사이클
- vue 히스토리 모드
- 정처기
- 2021 정보처리기사 실기
- router 네비게이션
- defaultProps
- Vue.js 입문
- Vue.js 시작하기
- vuex 새로고침
- 2021 정처기
- 백준 1110 시간 초과
- vue 로그인
- 2021 정처기 실기
- Props
- 정보처리기사
- 함수형 컴포넌트
- 중첩 라우트
- router replace
- 2021 정보처리기사
- React 시작하기
- propsTypes
- router go
- Today
- Total
개발 일기
[Vue.js 시작하기] - vuex로 중앙에서 상태 관리 하기 본문
Vuex란?
Vue.js 애플리케이션에 사용할 수 있는 상태 관리 라이브러리다. 이를 사용하면 모든 컴포넌트에 대한 중앙 집중식 저장소 역할을 할 수 있다. 상단 인스턴스는 여러개의 많은 하위 컴포넌트로 설계되어 구성된다.
여태까지 컴포넌트들끼리의 데이터 전달은 이벤트버스 등을 사용하였지만 공동의 상태를 공유하는 여러 컴포넌트가 있다는 등 프로젝트의 규모가 커진다면 이벤트 추적 관리에 힘들어질 수 있다. 이는 싱글톤으로 관리되지 않아 컴포넌트가 공유된 상태를 추출하지 않을 수 있다는 말과 같다.
이를 효율적으로 관리하기 위해서는 vuex 라이브러리를 사용하면 된다.
설치
npm install vuex --save
store란?
vuex로 상태관리를 하기 위해서는 store에 대해 먼저 이해해야 한다. 쉽게 말해서 store는 애플리케이션의 공유된 상태를 보유하고 있는 전역변수라고 할 수 있다.
다른 라이브러리 설치 후 종속성 추가할 때처럼 main.js에 바로 추가해도 되지만, src/store 아래에 js 파일을 만들어서 따로 관리할 예정이다. 이는 클래스도 성격별로 세분화되는 것처럼 이후에 전역변수도 여러개가 되는 경우 모듈화를 간편하게 하기 위해서다. 모듈화는 다음 글에서 다룰 예정이다.
index.js
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
},
getters:{
},
actions:{
}
})
export default store
store의 핵심 구성 요소들은 state, mutations, actions, getters이다.
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import axios from 'axios'
import store from '@/store/index.js' //store 전역변수를 import 해온다
Vue.prototype.$eventBus = new Vue();
Vue.prototype.$axios = axios
export default new Vuetify({
icons: {
iconfont: 'md' // 'md' || 'mdi' || 'fa' || 'fa4'
}
})
Vue.use(Vuetify)
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
vuetify: new Vuetify(),
store //Vue에 store 사용 명시
})
store를 외부 js 파일에 등록하였다면 이를 import 하여 Vue에서 사용한다는 것을 명시해야한다.
state
state는 여러 컴포넌트에서 공유할 공동의 상태를 의미한다.
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 1
}
})
export default store
<template>
<div>
{{ this.$store.state.count }}
</div>
</template>
store에 count라는 상태를 1이라고 정의해두었고, 어느 컴포넌트에서든 this.$store.state를 사용하여 공유할 상태에 있는 count 변수에 접근할 수 있다.
mutations
mutations는 state를 변경시키기 위한 유일한 방법이다. 또한 동기적 로직을 정의할 수 있다.
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
doubleCount(state) {
state.count = state.count * 2
},
multiCountAndNumber(state, payload) {
state.count = state.count * payload
}
}
})
export default store
mutations에 state를 변경할 수 있는 함수를 정의한 모습을 볼 수 있다. 첫번째 parameter는 원하는 state를 변경하기 위하여 state를 받는다. 만약 넘겨받은 것으로 state를 변경할 것이 있다면 두번째에 parameter에 추가 전달인자를 받는다. 위의 예제에서는 관용적으로 payload라고 사용했다.
<template>
<div>
<v-card max-width="500" class="mx-auto" :height="500" style="padding: 20px">
<v-row>
<v-col cols="6"> {{ this.$store.state.count }}</v-col>
<v-col cols="6">
<v-btn @click="doubleCount">store count double</v-btn></v-col
>
</v-row>
<v-row>
<v-col cols="6">
<v-text-field label="input number" v-model="number"></v-text-field>
</v-col>
<v-col cols="6">
<v-btn @click="multiInputNumber">multi store and input</v-btn>
</v-col>
</v-row>
</v-card>
</div>
</template>
<script>
export default {
data: function () {
return {
number: 0,
};
},
methods: {
doubleCount() {
this.$store.commit("doubleCount");
},
multiInputNumber() {
this.$store.commit("multiCountAndNumber", this.number);
},
},
};
</script>
this.$store.commit을 사용하여 이전에 mutations에 정의해둔 함수를 호출할 수 있다. doubleCount()를 보면 store의 doubleCount 핸들러를 실행시키므로 공유 상태 state중 count가 두배로 set 될 것이다. 다음으로 multiInputNumber()를 보면 store의 multiCountAndNumber를 실행시키므로 공유 상태 state중 count와 입력받은 값이 곱해진 결과값으로 count가 set 될 것이다.
getters
공동의 상태를 계산하여 state의 값을 반환하는 함수다. vue.js의 computed 속성과 비슷하다고 할 수 있다.
(computed 관련 참고 : 2021/01/14 - [Vue.js] - [Vue.js 시작하기] - computed vs watch)
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
alphabet: " ABC "
},
getters: {
getLowerCaseAlphabet(state) {
return state.alphabet.toLowerCase();
},
getTrimAlphabet(state) {
return state.alphabet.trim();
}
},
actions: {
}
})
export default store
<script>
computed: {
getLower() {
return this.$store.getters.getLowerCaseAlphabet;
},
getTrim() {
return this.$store.getters.getTrimAlphabet;
},
},
</script>
공동의 상태를 가공하는 경우가 여러 컴포넌트에 있을 때, 각 컴포넌트의 computed에서 같은 코드를 여러번 쓸 것을 getters에서 한번 제공하여 다른 컴포넌트에서 똑같이 쓸 수 있기 때문에 유지보수에 좋고 효율적인 코드를 사용할 수 있다.
actions
actions는 mutations와 유사하다. 다른 점은 mutations가 동기적 로직을 정의할 수 있는 반면 actions는 비동기적 로직을 정의할 수 있다. 따라서 각 컴포넌트에서 호출할 때 async/await 키워드를 사용할 수 있다. 그리고 actions 내부에서 mutations에 대한 commit이 가능하다.
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";
Vue.use(Vuex)
const HOST = ""
const store = new Vuex.Store({
state: {
animalList: [],
fruitList: []
},
mutations: {
setAnimalList(state, payload) {
state.animalList = payload
},
setFruitList(state, payload) {
state.fruitList = payload
}
},
actions: {
async getAllAnimals({ commit }) {
let response = null
try {
response = await axios(HOST + "/api/getAllAnimal")
}
catch (e) {
console.error(e)
}
commit("setAnimalList", response.data)
},
async getAllFriuts({ commit }) {
let response = null
try {
response = await axios(HOST + "/api/getAllFruits")
}
catch (e) {
console.error(e)
}
commit("setFruitList", response.data)
}
}
})
export default store
actions에 있는 함수의 파라미터에 commit 프로퍼티를 활성화 시켜서 내부에서 mutations에 대한 commit을 해주는 것을 볼 수 있다. 또한 비동기적 로직을 정의할 수 있기 때문에 만약 서버와의 통신이 필요하다면 axios를 사용하여 actions에 로직을 입력하면 된다.
(axios 참고 : 2021/01/18 - [Vue.js] - [Vue.js 시작하기] - axios 사용하여 서버 통신 하기 )
mutations와 마찬가지로 만약 넘겨받은 것으로 state를 변경할 것이 있다면 두번째에 parameter에 추가 전달인자를 받는다. 위의 예제에서는 관용적으로 payload라고 사용했다.
<script>
async created() {
await this.$store.dispatch("getAllAnimals");
await this.$store.dispatch("getAllFriuts");
}
</script>
컴포넌트에서는 this.$store.dispatch를 사용하여 호출할 수 있다. 위의 예제에서는 순서대로 animal과 fruit를 get 해야하므로 async/await 키워드를 사용했다.
사실 actions에서 활성화시킬 수 있는 프로퍼티는 많지만 다음에 store 모듈화에 대해 언급할 때 더 얘기하도록 하겠다.
결론
vuex를 쓴다면 규모가 커진 프로젝트의 이벤트 추적 및 데이터 관리를 더 쉽게 할 수 있을 것이다.
결론적으로 모든 컴포넌트는 컴포넌트 트리에 상관없이 공동의 상태에 액세스하거나 공동의 상태에 관련된 동작을 트리거 할 수 있다.
'Vue.js' 카테고리의 다른 글
[Vue.js] vuex store 모듈화하기 (0) | 2021.01.25 |
---|---|
[Vue.js] 다국어 처리 (vue-i18n 사용) (0) | 2021.01.21 |
[Vue.js 시작하기] - axios 사용하여 서버 통신 하기 (1) | 2021.01.18 |
[Vue.js 시작하기] - computed vs watch (0) | 2021.01.14 |
[Vue.js 시작하기] - Vuetify 로 웹 디자인 하기 (0) | 2021.01.13 |