Vuex
Vuex๋ ์ ํ๋ฆฌ์ผ์ด์ ์ํ ๊ด๋ฆฌ ํจํด + ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค. ๋ค๋ฅธ ์ํ๊ด๋ฆฌ ํจํด + ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋น๊ตํ์๋ Vue Reactivity ์ฒด๊ณ๋ฅผ ํจ์จ์ ์ผ๋ก ํ์ฉํด ํ๋ฉด ์ ๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ฅ์ ์ด ์๋ค.
Vue Reactivity
๋ทฐ๊ฐ ๋ฐ์ดํฐ ๋ณํ๋ฅผ ๊ฐ์งํ๊ณ ์๋์ผ๋ก ํ๋ฉด์ ๊ฐฑ์ ํ๋ ํน์ฑ
์ํ๊ด๋ฆฌ ๊ตฌ์ฑ์์

๊ตฌ์ฑ์์
์ค๋ช
state
์ปดํฌ๋ํธ๊ฐ ๊ณต์ ํ๋ data
view
๋ฐ์ดํฐ๊ฐ ํํ๋ template
actions
์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ฐ๋ผ ๋ฐ์ํ methods
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})
์ํ ๊ด๋ฆฌ๊ฐ ํ์ํ ์ด์
ํ์ ์ปดํฌ๋ํธ์์ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ๋ ๊ทธ ์ฌ์ด์ ์๋ง์ ์ปดํฌ๋ํธ๊ฐ ์กด์ฌํ๋ค๋ฉด, props๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ฒ ๋๋ฉด ๊ทธ ์ฌ์ด์ ๋ชจ๋ ์ปดํฌ๋ํธ์ props๋ฅผ ์ค์ ํด์ค์ผํ๋ฉฐ, ์ ์ง๋ณด์๊ฐ ํ๋ค์ด์ง๋ค.
์ด๋ฒคํธ ๋ฒ์ค๋ฅผ ํ์ฉํ๊ฒ๋๋ฉด ์-ํ์ ๋ฐ์ดํฐ ์ ๋ฌ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด์ง ์๊ณ ๋ ํ ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์์ง๋ง, ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ด ์๋ ์ ์ ์์ด ๋ง์ ๋ฐ์ดํฐ ํ๋ฆ์ด ๋๋ค๋ ๋ฌธ์ ์ ์ด ์๋ค.
์ฆ, ์ปดํฌ๋ํธ ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ ๋ฐ ์ด๋ฒคํธ ํต์ ๋ฑ์ ์ฌ๋ฌ ์ปดํฌ๋ํธ ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ฝ๊ฒ ๊ตฌ์กฐํ ํ๋ ๊ฒ(์ค์ ์ง์ค์ ์ ์ฅ์)์ด ์ํ๊ด๋ฆฌ(state management)์ด๋ค.

Basic
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount('#app')
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
});
vuex์ ์ค์ฌ์๋ store๊ฐ ์๋ค. "์ ์ฅ์"๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ํ(state)๋ฅผ ๋ณด์ ํ๊ณ ์๋ ์ปจํ ์ด๋์ด๋ค. Vuex ์ ์ฅ์๋ ๋ค๋ฅธ ์ ์ญ ๊ฐ์ฒด์ ๋ ๊ฐ์ง ์ฐจ์ด์ ์ด ์๋ค.
Vuex store๋ ๋ฐ์ํ์ด๋ค.
store์ state๋ฅผ ์ง์ ๋ณ๊ฒฝํ ์ ์๋ค. state๋ฅผ ๋ณ๊ฒฝํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋ช ์์ ์ธ commit์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
Getters
์ค์ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ๊ตฌ์กฐ์์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ์ค ํ๋๋ ๊ฐ ์ปดํฌ๋ํธ์์ Vuex์ ๋ฐ์ดํฐ์ ์ ๊ทผํ ๋ ์ค๋ณต๋ ์ฝ๋๋ฅผ ๋ฐ๋ณต ํธ์ถํ๊ฒ ๋๋ค๋ ๊ฒ์ด๋ค.
// App.vue
computed: {
getCounter() {
return this.$store.state.counter;
}
},
// Child.vue
computed: {
getCounter() {
return this.$store.state.counter;
}
},
Vuex์ state ๋ณ๊ฒฝ์ ๊ฐ ์ปดํฌ๋ํธ์์ ์ํํ๋ ๊ฒ์ด ์๋๋ผ ๋ค์๊ณผ ๊ฐ์ด Vuex์์ ์ํํ๋๋กํ๊ณ , ๊ฐ ์ปดํฌ๋ํธ์์ ์ํ ๋ก์ง์ ํธ์ถํ ์ ์๋ค.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 0
},
getters: {
getCounter( state ) {
return state.counter;
}
},
mutations: {
},
actions: {
},
modules: {
}
});
// App.vue
computed: {
parentCounter() {
this.$store.getters.getCounter;
}
},
// Child.vue
computed: {
childCounter() {
this.$store.getters.getCounter;
}
},
mapGetters
Vuex์ ๋ด์ฅ๋ helperํจ์์ด๋ค. mapGetters๋ก ๋ ์ง๊ด์ ์ด๊ฒ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค.
<!-- App.vue -->
<div id="app">
Parent counter : {{ parentCounter }}
</div>
// App.vue
import { mapGetters } from 'vuex'
export default({
computed: mapGetters({
parentCounter: 'getCounter'
})
});
๋๋ Vuex์ getters ์์ฑ ์ด๋ฆ๊ณผ ์ปดํฌ๋ํธ์ computed ์์ฑ์ ๋์ผํ๊ฒ ํด ๋ ๊ฐ๋จํ๊ฒ ์ ์ธํ ์ ์๋ค.
<!-- App.vue -->
<div id="app">
Parent counter : {{ getCounter }}
</div>
// App.vue
import { mapGetters } from 'vuex'
export default({
computed: mapGetters([
'getCounter'
]),
});
์ ๋ฐฉ๋ฒ๋ค์ ์ปดํฌ๋ํธ ์์ฒด์์ ์ฌ์ฉํ computed ์์ฑ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค. ES6์ ...
๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ ์ ์๋ค.
// App.vue
import { mapGetters } from 'vuex'
computed: {
...mapGetters([
'getCounter'
]),
anotherCounter() {
// ...
}
}
๋ค๋ง ...
๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด babel stage-2 ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๋ฐ ์ค์ ์ด ํ์ํ๋ค.
Mutations
Vuex์ state(๋ฐ์ดํฐ) ๊ฐ์ ๋ณ๊ฒฝํ๋ ๋ก์ง์ ์๋ฏธํ๋ค.
vs Getters
์ธ์๋ฅผ ๋ฐ์ Vuex์ ๋๊ฒจ์ค ์ ์๋ค.
computed๊ฐ ์๋ methods์ ๋ฑ๋กํ๋ค.
vs Actions
Mutations๋ ๋๊ธฐ ๋ก์ง์ ์ ์ํ๋ค.
Actions๋ ๋น๋๊ธฐ ๋ก์ง์ ์ ์ํ๋ค.
Mutations์ ์ฑ๊ฒฉ์ ์ ์ํ ๋ก์ง๋ค์ด ์์ฐจ์ ์ผ๋ก ์ผ์ด๋์ผ ๊ฐ ์ปดํฌ๋ํธ์ ๋ฐ์ ์ฌ๋ถ๋ฅผ ์ ๋๋ก ์ถ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Mutations์ ์ด์ฉํด ์ํ ๋ณํ๋ฅผ ๋ช ์์ ์ผ๋ก ์ํํจ์ผ๋ก์จ testing, debugging, Vue์ Reactive ์ฑ์ง ์ค์๋ฅผ ํ ์ ์๋ค.

๋ค์๊ณผ ๊ฐ์ด commit
์ผ๋ก state๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
counter: 0
},
getters: {
getCounter(state) {
return state.counter;
}
},
mutations: {
addCounter(state, payload) {
return state.counter++;
}
}
});
export default {
methods: {
addCounter() {
this.$store.commit('addCounter');
},
subCounter() {
this.$store.commit('subCounter');
}
},
...
};
.commit
์ ์ด์ฉํ์ฌ mutations ์ด๋ฒคํธ๋ฅผ ํธ์ถํ์ฌ ์ํ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
์ธ์ ๊ฐ ๋๊ธฐ๊ธฐ
this.$store.commit('subCounter', 10);
this.$store.commit('subCounter', {
value: 10,
arr: ["1", "3"]
});
ํน์ ํ ๊ฐ์ ๋๊ธฐ๊ณ ์ถ์ผ๋ฉด ๋๋ฒ์งธ ์ธ์๋ฅผ ์ถ๊ฐํด ์ ๋ฌํ ์ ์๋ค. ์ ๋ฌ๋ ์ธ์ ๊ฐ์ vuex์์ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ์ ์ ์๋ค.
mutations: {
addCounter(state, payload) {
state.counter = payload.value;
}
}
์ฌ๊ธฐ์ ๋ฐ์ดํฐ ์ธ์๋ช ์ ๋ณดํต payload๋ฅผ ์ฌ์ฉํ๋ค.
mapMutations
Vuex์ ๋ด์ฅ๋ helper๋ก mapMutations๋ฅผ ์ด์ฉํด ์ฝ๋ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์๋ค.
// App.vue
import { mapMutations } from 'vuex'
methods: {
...mapMutations([
'addCounter'
]),
...mapMutations({
addCounter: 'addCounter'
})
}
Vuex ์ Mutations ๋ฉ์๋ ๋ช ๊ณผ App.vue ๋ฉ์๋ ๋ช ์ด ๋์ผํ ๋ [] ์ฌ์ฉํ๋ฉฐ, ๋ช ์นญ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ {}๋ฅผ ์ฌ์ฉํ๋ค.
Actions
Mutations๋ state๊ด๋ฆฌ๋ฅผ ์ฃผ๋ก ํ๋ฉฐ, ์ํ ๊ด๋ฆฌ๋ ํ ๋ฐ์ดํฐ์ ๋ํด ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๊ด์ฌํ๋ ๊ฒ์ ํจ์จ์ ์ผ๋ก ํ๊ธฐ ์ํจ์ด๋ฏ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ก์ง์ ํฌํจํ์ง ์๋๋ค. Actions์์ ๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ก์ง์ ๊ด๋ฆฌํ๋ค.
setTimeout()
์ด๋ ์๋ฒ์์ http ํต์ ๊ณผ ๊ฐ์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ค๋ ์๊ฐ์ด ์์ธก๋์ง ์๋ ๋ก์ง์ actions์ ์ ์ธํ๋ค.
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
...
actions: {
addCounter(context) {
return context.commit('addCounter');
}
}
});
// App.vue
methods: {
// Actions ๋ฅผ ์ด์ฉํ ๋
addCounter() {
this.$store.dispatch('addCounter');
}
},
Actions๋ฅผ ํธ์ถํ ๋๋ .dispatch()
๋ฅผ ์ด์ฉํ๋ค.

Actions์์ ์ธ์๋ฅผ ๋๊ธฐ๋ ๋ฐฉ๋ฒ์ Mutations์ ์ ์ฌํ๋ค.
mapActions
mapActions๋ ์์ map๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
import {mapActions} from 'vuex';
export default {
methods: {
...mapActions([
'asyncIncrement',
'asyncDecrement'
])
},
}
์ฐธ์กฐ
Last updated
Was this helpful?