๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

vuex

๐Ÿ“ข ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

  • ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„  Vuex๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด๊ณ , ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณธ๋‹ค.
  • Vue CLI๋กœ ์„ค์น˜ํ•œ Vue.js ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ์—์„œ ์ง„ํ–‰ํ–ˆ๋‹ค. Vuex๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์—, ์•„๋ž˜ ๋ฐฉ๋ฒ•์œผ๋กœ Vue.js ํ”„๋กœ์ ํŠธ๋ฅผ ์„ค์น˜ํ•ด์•ผํ•œ๋‹ค.
    1. Intellij IDE ๋˜๋Š” WebStorm IDE
      • File - New - Project - Vue.js
    2. npm
      • npm i -g @vue/cli
      • vue create 'ํ”„๋กœ์ ํŠธ ๋ช…'

โœŒ Vuex ๋ž€?

Vuex๋Š” ํ•œ๋งˆ๋””๋กœ ์–˜๊ธฐํ•˜์ž๋ฉด ์ƒํƒœ(state)๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.
์—ฌ๊ธฐ์„œ ์ƒํƒœ๋ž€ ๋ฌด์—‡์ผ๊นŒ?

new Vue({
  // ์ƒํƒœ
  data () {
    return {
      count: 0
    }
  },
  // ๋ทฐ
  template: `
    <div>{{ count }}</div>
  `,
  // ์•ก์…˜
  methods: {
    increment () {
      this.count++
    }
  }
})

์—ฌ๊ธฐ ๊ฐ„๋‹จํ•œ Vue.js ์•ฑ์ด ์žˆ๋‹ค.
์—ฌ๊ธฐ์„œ data() ๋ฅผ ์šฐ๋ฆฐ "์ƒํƒœ(state)" ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. (์ปดํฌ๋„ŒํŠธ ๊ฐ„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ)
๋ฐ”๋กœ ์ด ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด Vuex ์ด๋‹ค.

โœŒ Vuex๋Š” ์–ธ์ œ, ์™œ ํ•„์š”ํ•œ๊ฐ€?

prop์ด๋‚˜ ref ๋“ฑ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ(์ƒํƒœ)๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ๊ตณ์ด Vuex๊ฐ€ ํ•„์š”ํ• ๊นŒ?

  • ๊ณตํ†ต์˜ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ง€๋‚˜์น˜๊ฒŒ ์ค‘์ฒฉ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ต๊ณผํ•˜๋Š” prop์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค. ์ด๋Š” ๋‚˜์ค‘์— ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ํž˜๋“  ๋‚œํ•ดํ•œ ์ฝ”๋“œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ณตํ†ต์˜ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด ์ƒํƒœ๊ฐ€ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ ์ƒํƒœ๋กœ ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•œ๋‹ค. Vue๋Š” ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฅด๊ธฐ๋•Œ๋ฌธ์—, ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•œ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒฝ์šฐ, ํ˜•์ œ ์ปดํฌ๋„ŒํŠธ๊ฐ„์˜ ์ƒํƒœ๊ณต์œ /๊ด€๋ฆฌ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

์ด ๋•Œ ์šฐ๋ฆฐ Vuex๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŽ์€ ์ค‘๋Œ€ํ˜• ๊ทœ๋ชจ์˜ SPA ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ธ๋‹ค.

 

๐Ÿšจ ์ฃผ์˜

์•„๋ž˜์—์„œ ์„ค๋ช…ํ•˜๊ฒ ์ง€๋งŒ Vuex ๋Š” store(์ €์žฅ์†Œ)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
์ฆ‰, ์ƒํƒœ(state)์˜ ์ €์žฅ์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์ธ๋ฐ, ์ด ์ €์žฅ์†Œ๋ผ๋Š” ๋ง ๋•Œ๋ฌธ์— Vuex๊ฐ€ ์„ธ์…˜/์ฟ ํ‚ค localStorage ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ซํžˆ์ง€ ์•Š๋Š” ์ด์ƒ ๊ณ„์† ์œ ์ง€๋˜๋Š”, Vuex ์ €์žฅ์†Œ์— ์ƒํƒœ(state)๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ Vuex ์˜ ์ƒํƒœ๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ ๊ณ ์นจ์‹œ ์ดˆ๊ธฐํ™” ๋œ๋‹ค.
Vuex๋Š” ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„์˜ data() ๊ฐ€ ๊ทธ์ € ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‹จ์œ„์˜ data()๊ฐ€ ๋œ ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. data()๊ฐ€ localStorage์— ์ €์žฅ๋˜์ง„ ์•Š๋Š”๋‹ค. ์ƒˆ๋กœ๊ณ ์นจํ•˜๋ฉด ๋‹น์—ฐํžˆ ์ดˆ๊ธฐํ™”๋จ..๐Ÿ˜…
์ƒํƒœ๋ฅผ ์ƒˆ๋กœ๊ณ ์นจ ์‹œ์—๋„ ์œ ์ง€ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด vuex-persistedstate(state - localstorage ๋™๊ธฐํ™” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ) ๊ฐ™์€ ๋˜ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

โœŒ Vuex ์„ค์น˜ํ•˜๊ธฐ

vue

vue add vuex

 

npm

npm install vuex --save

Yarn

yarn add vuex

 

(๋‚˜๋Š” npm ์œผ๋กœ ์„ค์น˜ํ•ด์คฌ๋‹ค)

 

Vuex๋Š” ์ƒํƒœ(state)๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ์ €์žฅ์†Œ(store)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
Vuex๊ฐ€ ์„ค์น˜๋˜์—ˆ๋‹ค๋ฉด ์ด ์ €์žฅ์†Œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์ฃผ์ž.

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export const store = new Vuex.Store({
    state: {

    }
    // ...
});

/src/store.js

 

/src ๊ฒฝ๋กœ์— store.js ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์œ„์™€ ๊ฐ™์ด ์ž…๋ ฅํ•ด์คฌ๋‹ค.
Vue.use() ๋ฅผ ํ†ตํ•ด Vue๊ฐ€ Vuex ์‚ฌ์šฉํ•จ์„ ์„ ์–ธํ•˜๊ณ , store ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์ค€ ๊ฒƒ์ด๋‹ค.

 

import Vue from 'vue'
import App from './App.vue'
import { store } from "./store";

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store: store,
}).$mount('#app');

/src/main.js

 

main.js ์—์„  ๋งŒ๋“ค์–ด์ค€ store.js ๋ฅผ import ํ•ด์˜จ ๋’ค Vue ์ธ์Šคํ„ด์Šค์— ์ฃผ์ž…ํ•˜์ž.

 

์—ฌ๊ธฐ์„œ ์ž ๊น ์œ„ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์ž๋ฉด,

Vue.config.productionTip ๋Š” Vue ์•ฑ์ด ์ฒ˜์Œ ์‹คํ–‰ ๋  ๋•Œ ๋‚˜์˜ค๋Š” ๊ฒฝ๊ณ ๋ฌธ(๋ฐฐํฌ์— ๋Œ€ํ•œ ํŒ)์„ ์ถœ๋ ฅํ•  ๊ฒƒ์ธ์ง€ ๋ฌผ์–ด๋ณด๋Š” ๋‚ด์šฉ์ด๋‹ค.
false๋กœ ์„ค์ •ํ•˜๋ฉด ๊ฒฝ๊ณ ๋ฌธ(๋ฐฐํฌ์— ๋Œ€ํ•œ ํŒ)์„ ์ถœ๋ ฅํ•˜์ง€ ์•Š๋Š”๋‹ค.
default ๋Š” false ์ด๋‹ค.

 

render: h => h(App)์€ ๋„ค ๋‹จ๊ณ„์— ๊ฑฐ์ณ์„œ ES6๋กœ ๋ณ€ํ˜•๋œ ๋ฉ”์†Œ๋“œ์ด๋‹ค.

// #1
render: function (createElement) {
    return createElement(App);
}

// #2
render (createElement) {
    return createElement(App);
}

// #3
render (h){
    return h(App);
}

// #4
render: h => h(App);

ES6 ๋ฌธ๋ฒ•์ด๋ผ๋Š” ๊ฒƒ์€ ์ด์ œ ์•Œ๊ฒ ๊ณ ...
์ •ํ™•ํžˆ render() ๋ผ๋Š” ๊ฒƒ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š” ๊ฑธ๊นŒ?

์œ„ ์ฝ”๋“œ์—์„œ #1์„ ๋ณด๋ฉด render๋Š” ์‹ค์งˆ์ ์œผ๋กœ createElement()์˜ ๋ฐ˜ํ™˜ ๊ฐ’์ด๋ผ๋Š” ๊ฑธ ์•Œ์ˆ˜ ์žˆ๋‹ค.
์—ฌ๊ธฐ์„œ createElement() ๋ž€, Virtual DOM(๊ฐ€์ƒ ๋”)์„ ๋งŒ๋“œ๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค.

 

Virtual DOM(๊ฐ€์ƒ๋”)

<div>
  <h1>My title</h1>
  Some text content
  <!-- TODO: Add tagline  -->
</div>

HTML DOM Node Tree

์œ„ ์ด๋ฏธ์ง€๋Š” HTML ์ฝ”๋“œ๋ฅผ DOM ๋…ธ๋“œ ํŠธ๋ฆฌ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์ด๋‹ค.
ํ…์ŠคํŠธ, ์‹ฌ์ง€์–ด ์ฃผ์„ ์กฐ์ฐจ ํ•˜๋‚˜์˜ ๋ฉ์–ด๋ฆฌ(๋…ธ๋“œ)๊ฐ€ ๋˜์–ด ํŠธ๋ฆฌ์˜ ํ•œ ๋ถ€๋ถ„์ด ๋œ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
์ด๋Ÿฌํ•œ ๋…ธ๋“œ์˜ ์–ด๋Š ํ•œ ๋ถ€๋ถ„์ด ์—…๋ฐ์ดํŠธ ๋˜์–ด์•ผํ•  ๋•Œ, ์ „์ฒด ํŠธ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒƒ์€ ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ์ ์ผ ์ˆ˜๋ฐ–์— ์—†๋‹ค.
๊ทธ๋ž˜์„œ ๊ณ ์•ˆ๋œ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ Virtual DOM์ด๋‹ค.

๊ฐ€์ƒ ๋”์€ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•œ ๋…ธ๋“œ ์ •๋ณด๋งŒ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค.
๋•Œ๋ฌธ์— ์šฐ๋ฆฐ ์ˆ˜์ •์„ ์›ํ•˜๋Š” ๋…ธ๋“œ๋งŒ ์—…๋ฐ์ดํŠธ ์‹œ์ผœ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ „์ฒด ๋…ธ๋“œํŠธ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•˜์ง€ ์•Š๊ณ ๋„!
์ฐธ๊ณ ๋กœ ์ด ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•œ ๊ฐ€์ƒ ๋”์˜ ๋…ธ๋“œ๋“ค์„ VNode๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ด ๊ฐ€์ƒ ๋”์„ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ”๋กœ createElement()์ด๋‹ค.
์‚ฌ์šฉ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด์ž

์œ„ ์ฝ”๋“œ์˜ h1 ํƒœ๊ทธ ๋‚ด์˜ title ๋ถ€๋ถ„๋งŒ ๊ฐฑ์‹ ์‹œ์ผœ๋ณด๊ฒ ๋‹ค.

render: function (createElement) {
  return createElement('h1', this.blogTitle)
}

h1 ํƒœ๊ทธ์˜ ๋‚ด์šฉ์„ this.blogTitle๋กœ ๋ณ€๊ฒฝํ•˜๊ฒ ๋‹ค๋Š” ๋œป์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์ž ๊น, ์˜๋ฌธ์ ์ด ๋“ค์ง€ ์•Š๋Š”๊ฐ€?

render: function (createElement) {
    return createElement(App);
}

์œ„ ์ฝ”๋“œ์—์„  createElement์˜ ์ „๋‹ฌ ์ธ์ž๊ฐ€ App์œผ๋กœ ํ•˜๋‚˜์˜€๋Š”๋ฐ,
๊ฐ€์ƒ ๋” ์˜ˆ์ œ์—์„  h1, this.blogTitle ์œผ๋กœ ์ „๋‹ฌ์ธ์ž๊ฐ€ ๋‘๊ฐœ์ธ ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

createElement(renderElement: String | Component, children: String | Array)
createElement(renderElement: String | Componenet, definition: Object, children: String | Array)

๊ฒฐ๋ก ์€, createElement์˜ ์ „๋‹ฌ์ธ์ž๋Š” 2๊ฐœ์ผ์ˆ˜๋„, 3๊ฐœ์ผ ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
App ์ฒ˜๋Ÿผ ์ „๋‹ฌ ์ธ์ž๋ฅผ ํ•˜๋‚˜๋งŒ ๋ฐ›์•„ ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋ฅผ ๊ฐ€์ƒ๋”์œผ๋กœ ๋ Œ๋”๋ง ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ณ ,
์ „๋‹ฌ ์ธ์ž๋ฅผ ๋‘๊ฐœ(h1, this.blogTitle) ๋ฐ›์•„ h1 element ๋ฅผ this.blogTitle์ด๋ผ๋Š” ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธํ•œ๋‹ค๊ณ  ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ - ๊ณต์‹๋ฌธ์„œ

 

์ด๋กœ์จ render: h => h(App); ์— ๋Œ€ํ•ด ์กฐ๊ธˆ์ด๋‚˜๋งˆ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.
์š”์•ฝํ•˜์ž๋ฉด,
render: h => h(App) ํ•จ์ˆ˜๋Š” ์‚ฌ์‹ค createElement(App)์˜ ๋ฐ˜ํ™˜ ๊ฐ’์ด๊ณ ,
createElement()๋Š” ๊ฐ€์ƒ ๋”์„ ๋งŒ๋“ค์–ด ๋ Œ๋”๋ง ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
๊ทธ๋ฆฌ๊ณ  createElement๋ฅผ h๋กœ ์š”์•ฝํ•œ ๋’ค, ES6์˜ ํ™”์‚ดํ‘œํ•จ์ˆ˜๋ฅผ ์“ด ๊ฒƒ์ด ์ง€๊ธˆ์˜ render: h => h(App) ๋ผ๋Š” ๊ฒƒ์ด๋‹ค.
(h ๋Š” hyperscript์˜ ์•ฝ์ž๋กœ HTML ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์˜๋ฏธํ•จ.)

store: store ๋Š” Vue์— Vuex(store)๋ฅผ ์ฃผ์ž…ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.
๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ router ๋„ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค.

โœŒ Vuex์˜ ํ•ต์‹ฌ ์†์„ฑ

์œ„ store.js์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด state ์†์„ฑ์„ ์จ์คฌ๋˜ ๊ฒƒ ๊ธฐ์–ต๋‚˜๋Š”๊ฐ€?

export const store = new Vuex.Store({
    state: {

    }
    // ...
});

/src/store.js

 

state์™€ ๊ฐ™์€ ์†์„ฑ์ด store ๋‚ด์—” ํฌ๊ฒŒ 5๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

  • state
  • getters
  • mutations
  • actions
  • modules

์ง€๊ธˆ๋ถ€ํ„ฐ ์ด 5๊ฐ€์ง€ ์†์„ฑ์— ๋Œ€ํ•ด ์ฐจ๊ทผ์ฐจ๊ทผ ์•Œ์•„๋ณด์ž.

๐Ÿ• state

state๋Š” ์ƒํƒœ(state)์˜ ์ง‘ํ•ฉ์ด๋‹ค.
Vuex ๋Š” ๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ(single state tree) ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ง‘ํ•ฉ ๋‚ด์—์„œ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

 

๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ(single state tree)

๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ๋ž€, ์‰ฝ๊ฒŒ ๋งํ•ด์„œ ํ•˜๋‚˜์˜ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํ•˜๋‚˜์˜ store๋งŒ ๊ฐ€์ง„๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
ํ•˜๋‚˜์˜ store๋งŒ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ state์˜ ์ƒํƒœ(snapshot)๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ๋ผ๋Š” ๋ง์ด ๋‹ค์†Œ ์–ด๋ ต๊ฒŒ ๋Š๊ปด์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด์ž

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export const store = new Vuex.Store({
    state: {
        count: 0
    }
});

/src/store.js

 

<template>
    <div>
        This is A View
        {{ count }}
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count
            }
        }
    }
</script>

<style scoped>

</style>

/src/components/A.vue

 

<template>
    <div>
        This is B View
        {{ count }}
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count
            }
        }
    }
</script>

<style scoped>

</style>

B.vue

 

ํ˜„์žฌ store์˜ state์—” count๋ผ๋Š” ์ƒํƒœ๊ฐ€ ์žˆ๊ณ , ๊ทธ ์ƒํƒœ๋ฅผ ๊ฐ๊ฐ A์™€ B ํ™”๋ฉด์—์„œ ๋ถˆ๋Ÿฌ์™”๋‹ค

 

A, B ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ํ™”๋ฉด์— ๋„์›Œ๋ดค๋‹ค.

๋‘˜ ๋‹ค 0์œผ๋กœ count ๊ฐ€ ๋™์ผํ•˜๊ฒŒ ์ถœ๋ ฅ๋œ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์ด ์ƒํƒœ์—์„œ A ์ปดํฌ๋„ŒํŠธ์—์„œ count์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผœ๋ณด์ž.
+ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค๊ณ  ํด๋ฆญํ•˜๋ฉด count์˜ ๊ฐ’์ด ์ฆ๊ฐ€๋˜๋„๋ก ํ•ด๋ณด์•˜๋‹ค.

<template>
    <div>
        This is A View
        {{ count }}
        <button @click="plus">+</button>
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count
            }
        },
        methods: {
            plus() {
                this.$store.state.count++
            }
        }
    }
</script>

<style scoped>

</style>

/src/components/A.vue

 

'+' ๋ฅผ ๋ˆ„๋ฅธ ๊ฒฐ๊ณผ

A ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ์ฆ๊ฐ€๋ฅผ ์‹œ์ผฐ๋Š”๋ฐ, B ์ปดํฌ๋„ŒํŠธ์˜ count ๋„ ์ฆ๊ฐ€๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋Š” ๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๊ฒฐ๊ณผ์ด๋‹ค. ๋ง๊ทธ๋Œ€๋กœ state์˜ ์ƒํƒœ๊ฐ€ ๋‹จ์ผ(์œ ์ผ)ํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

store์˜ state ํ™”๋ฉด์— ์ถœ๋ ฅ ์‹œํ‚ค๊ธฐ

์œ„ ๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์ด๋ฏธ state๋ฅผ ํ™”๋ฉด์— ์ถœ๋ ฅ์‹œํ‚ค๋Š” ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด์•˜์ง€๋งŒ ํ•œ๋ฒˆ ๋” ์‚ดํŽด๋ณด์ž.
๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ state์˜ ์ƒํƒœ๋ฅผ Vue ์ปดํฌ๋„ŒํŠธ ํ™”๋ฉด์— ์ถœ๋ ฅ์‹œ์ผœ๋ณด๊ฒ ๋‹ค.

export const store = new Vuex.Store({
    state: {
        count: 0
    },
});

/src/store.js

 

๋จผ์ € store.js ํŒŒ์ผ์— state.count๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ๋‹ค. store์— count ์ƒํƒœ๋ฅผ ๋ณด๊ด€ํ•œ ๊ฒƒ์ด๋‹ค.
์ด ์ €์žฅ์†Œ์— ๋ณด๊ด€๋œ count๋ฅผ Vue ์ปดํฌ๋„ŒํŠธ์— ์ถœ๋ ฅ์‹œ์ผœ๋ณด๊ฒ ๋‹ค.
store์˜ count๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋‹จ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—,
๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ count์˜ ์ƒํƒœ๊ฐ€ ๋ณ€์ด์‹œ์ผฐ๋‹ค๋ฉด ํ˜„์žฌ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ๊ทธ ๋ณ€ํ™”๋œ ์ƒํƒœ๊ฐ€ ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.
๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ Vue์˜ computed ์†์„ฑ์„ ํ†ตํ•ด store์˜ state๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

<template>
    <div>
        {{ count }}
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count
            }
        }
    }
</script>

<style scoped>

</style>

/src/components/Counter.vue

 

Counter.vue๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  computed์— this.$store.state.count ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ™”๋ฉด์— ์ถœ๋ ฅ์‹œ์ผฐ๋‹ค.
0์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถœ๋ ฅ๋œ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.๐ŸŽ‰

mapState

computed์— ์„ ์–ธ๋œ ์ƒํƒœ(state)๊ฐ€ ๋งŽ์œผ๋ฉด, ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต์ ์ด๊ณ  ์žฅํ™ฉํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
์˜ˆ๋ฅผ๋“ค๋ฉด, ์ด๋Ÿฐ์‹์œผ๋กœ.

computed: {
    count() {
        return this.$store.state.count
    },
    age() {
        return this.$store.state.age
    },
    isStudent() {
        return this.$store.state.isStudent
    }
}

this.$sotre.state ๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š”๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Vuex๋Š” mapState ๋ผ๋Š” Helper๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋‹ค.

import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // #1 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
    count: state => state.count,

    // #2 ๋ฌธ์ž์—ด๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ (`state => state.count`์™€ ๊ฐ™๋‹ค.)
    countAlias: 'count',

    // #3 `this`๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ์ƒํƒœ์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค
    countPlusLocalState (state) {
      return state.count + this.localCount
    }

    // #4 this.count๋ฅผ store.state.count์— ๋งคํ•‘ํ•œ๋‹ค.
      'count'
  })
}

mapState๋ฅผ ํ™œ์šฉํ•ด ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์—†์• ๊ณ  state๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
mapState๋ฅผ ๊ธฐ์กด ๋กœ์ปฌ์˜ computed์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ฐ์ฒด ์ „๊ฐœ ์—ฐ์‚ฐ์ž(Object Spread Operator) ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ „๊ฐœ๊ตฌ๋ฌธ์ด๋ผ๊ณ ๋„ํ•œ๋‹ค (...)

 computed: {
  localComputed () { /* ... */ }, // ๊ธฐ์กด์˜ computed
  ...mapState({ 
    // ...
  })
}

๐Ÿ“ข ์ปดํฌ๋„ŒํŠธ์—๋Š” ์—ฌ์ „ํžˆ ๋กœ์ปฌ ์ƒํƒœ(data())์— ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
Vuex๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ด์„œ ๋ชจ๋“  ์ƒํƒœ๋ฅผ store์— ๋„ฃ์„ ํ•„์š”๋Š” ์—†๋‹ค.

๐Ÿ• getters

state๋ฅผ ๊ณ„์‚ฐํ•œ ๊ฐ’์„ ์‚ฌ์šฉํ•ด์•ผํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
๋‹จ์ผ ์ƒํƒœ ํŠธ๋ฆฌ ํŒŒํŠธ์—์„œ ์šฐ๋ฆฐ count๋ฅผ A ์ปดํฌ๋„ŒํŠธ์—์„œ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์˜ˆ์ œ๋ฅผ ์ง„ํ–‰ํ–ˆ์—ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ๊ฐ๊ฐ์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ state๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋ฉด ๋ฐ˜๋ณต ํ˜ธ์ถœ์ด ์žฆ์•„์ ธ ๋น„ํšจ์œจ์ ์ธ ๋กœ์ง์ด ๋œ๋‹ค.


getters๋Š” ๊ทธ๋Ÿฐ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ์†์„ฑ์ด๋‹ค.
getters๋Š” state์— ๋Œ€ํ•œ ๋ณ€์ด๋ฅผ ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง„ํ–‰ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ, Vuex์—์„œ ๋ณ€์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฐ ์ปดํฌ๋„ŒํŠธ์—์„œ state๋ฅผ ํ˜ธ์ถœ๋งŒ ํ•˜๋„๋ก ํ•˜๊ฒŒ ํ•œ๋‹ค.

 

์˜ˆ์ œ๋กœ ์‚ดํŽด๋ณด์ž.
์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋กœ์ง์„ Vuex ์˜ getters ์— ๋„ฃ์–ด๋ณผ ๊ฒƒ์ด๋‹ค.

export const store = new Vuex.Store({
    state: {
        count: 0
    },
    getters: {
        increaseCount(state) {
            return ++state.count;
        }
    }
});

/src/store.js

 

<template>
    <div>
        {{ count }}
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.getters.increaseCount;
            }
        }
    }
</script>

<style scoped>

</style>

/src/components/Counter.vue

 

1 ์ด๋ผ๋Š” ์ฆ๊ฐ€๋œ ๊ฐ’์ด ํ™”๋ฉด์— ์ถœ๋ ฅ๋˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
getters๋Š” ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜๊ฐ’์ด ์žˆ์–ด์•ผํ•œ๋‹ค. ์ด ๋ฐ˜ํ™˜๊ฐ’์€ state ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ฐ™์€ getters๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

getters: {
        increaseCount:(state, getters) => {
            return getters.getCurCount;
        },
        getCurCount: (state) => {
            return state.count;
        }
    }

getters๋Š” ๋”ฐ๋กœ ์ „๋‹ฌ์ธ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†๋‹ค. ๊ณง ์‚ดํŽด๋ณผ mutations ์™€์˜ ์ฐจ์ด์  ์ด๊ธฐ๋„ ํ•˜๋‹ค.
ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ getters์— ์ „๋‹ฌ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

getters ๋Š” ๋”ฐ๋กœ ์ „๋‹ฌ์ธ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†๋‹ค๊ณ  ๋˜์–ด์žˆ๋Š”๋ฐ, increaseCount:(state, getters) => {}
์—ฌ๊ธฐ์„œ ๋ณด์ด๋Š” state์™€ getters๋Š” ๋ฌด์—‡์ผ๊นŒ?
์ด๋Š” Vuex getters์˜ default ์ „๋‹ฌ ์ธ์ž๋กœ, ๋ง๊ทธ๋Œ€๋กœ ํ˜„์žฌ state์™€ getters๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
์ฒซ๋ฒˆ์งธ ์ „๋‹ฌ์ธ์ž๋Š” state, ๋‘๋ฒˆ์งธ๋Š” getters, ์„ธ๋ฒˆ์งธ๋Š” rootState, ๋„ค๋ฒˆ์งธ๋Š” rootGetters์ด๋‹ค.
(rootState ์— ๊ด€๋ จํ•ด์„œ๋Š” modules ํŒŒํŠธ์—์„œ ์ž์„ธํžˆ ๋‹ค๋ค„๋ณธ๋‹ค.
state์™ธ ์ „๋‹ฌ์ธ์ž๋Š” ์˜ˆ์ œ์—์„œ๋„ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์˜ต์…˜์ด๋‹ค.(์จ๋„ ๋˜๊ณ  ์จ์ฃผ์ง€ ์•Š์•„๋„ ๋˜๋Š”...)

getters: {
        increaseCount: (state) => (num) => {
            return state.count + num;
        },
    }

// ๊ฐ™์€ ์˜๋ฏธ
increaseCount: (function (state) {
  return function (num) {
    return state.count + num;
  };
});

mapGetters

state ํŒŒํŠธ์—์„œ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š” ๊ฑธ ๋ง‰๊ธฐ ์œ„ํ•ด mapState๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค.
getters๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ mapGetters๋ฅผ ์‚ฌ์šฉํ•ด ์ฝ”๋“œ์˜ ๋ฐ˜๋ณต์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.
(์ด ์—ญ์‹œ, ๋‹ค๋ฅธ computed ์†์„ฑ๋“ค๊ณผ ํ•จ๊ป˜ ์“ฐ๊ณ ์‹ถ๋‹ค๋ฉด ์ „๊ฐœ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.)

computed: {
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }

getter๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ๋งคํ•‘ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
store.getters.doneTodoxCount๋ฅผ this.doneCount๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๋งคํ•‘ํ•œ ๊ฒฝ์šฐ์ด๋‹ค.

...mapGetters({
  doneCount: 'doneTodosCount'
})

๐Ÿ• mutations

mutations๋„ getters์™€ ๋™์ผํ•˜๊ฒŒ state์˜ ๊ฐ’์„ ๋ณ€ํ™˜ ์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

 

mutations์™€ getters์˜ ์ฐจ์ด์ 

  1. mutations๋Š” ์ „๋‹ฌ์ธ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  2. getters๋Š” computed์— ๋“ฑ๋ก ํ–ˆ์ง€๋งŒ mutations๋Š” methods์— ๋“ฑ๋กํ•œ๋‹ค.

mutations๋Š” ๋™๊ธฐ์  ๋กœ์ง์„ ์ •์˜ํ•œ๋‹ค๋Š” ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
๋™๊ธฐ์ , ๋ง๊ทธ๋Œ€๋กœ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ณ€์ด๊ฐ€ ์ง„ํ–‰๋œ๋‹ค๋Š” ๋œป์ด๋‹ค.
์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•˜๋‚˜์˜ ์ƒํƒœ๋ฅผ ๋ณ€์ด์‹œํ‚จ๋‹ค๋ฉด ํ˜„์žฌ state๊ฐ€ ์–ด๋–ค์ง€ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์šธ ๊ฒƒ์ด๋‹ค.
๊ทธ ๋•Œ, mutations์— ์ •์˜ํ•œ ์ƒํƒœ๋ณ€์ดํ•จ์ˆ˜๋ฅผ commit ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด ์ƒํƒœ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด์ž.

export const store = new Vuex.Store({
  // ...
  mutations: {
    addCounter: function (state) {
      return state.counter++;
    }
  }
});

/src/store.js

 

<template>
    <div>
        {{ count }}
        <button @click="increaseCnt">+</button>
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.count;
            }
        },
        methods: {
            increaseCnt() {
                this.$store.commit('addCounter');
            }
        }
    }
</script>

<style scoped>

</style>

Counter.vue

 

store.js ์˜ mutations์— addCounter๋ผ๊ณ  count ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ–ˆ๋‹ค.
Counter.vue์—์„  methods๋‚ด์— commit์„ ์‚ฌ์šฉํ•˜์—ฌ addCounter๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.

 

+๋ฅผ ๋ˆ„๋ฅด๋ฉด count๊ฐ€ ์ฆ๊ฐ€ํ•จ

mutations๋ฅผ ํ†ตํ•ด count ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

commit์€ type ์†์„ฑ์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋กœ mutations์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

store.commit({
  type: 'addCounter',
  amount: 10 // ์ „๋‹ฌ์ธ์ž (์•„๋ž˜์—์„œ ์„ค๋ช…)
})

mutations๋Š” ๋™๊ธฐ์  ๋กœ์ง์„ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— this.$store.mutations.addCounter ๋“ฑ์œผ๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค.
๋ฐ˜๋“œ์‹œ commit์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•ด state์˜ ์ถ”์ ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์•ผํ•œ๋‹ค.

mutations์˜ ์ „๋‹ฌ ์ธ์ž

getters์™€ mutations์˜ ์ฐจ์ด์ ์œผ๋กœ ์ „๋‹ฌ์ธ์ž๊ฐ€ ์žˆ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค.
mutations์—์„œ ์–ด๋–ป๊ฒŒ ์ „๋‹ฌ์ธ์ž๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์ง€ ์‚ดํŽด ๋ณด์ž.

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}

store.js

 

methods: {
    increaseCnt(num) {
        store.commit('increment', num)
    }
}

Counter.vue

 

commit์— ์ถ”๊ฐ€ ์ „๋‹ฌ ์ธ์ž๋ฅผ ๋ถ™์—ฌ ์ „๋‹ฌ์ธ์ž๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด ์ถ”๊ฐ€ ์ „๋‹ฌ ์ธ์ž ๋ถ€๋ถ„์„ payload๋ผ๊ณ  ํ•œ๋‹ค.
payload๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์ „๋‹ฌ ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

store.js

 

store.commit('increment', {
  amount: 10
})

Counter.vue

 

mapMutations

mapState, mapGetters ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ mapMutations๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ mutations๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
mapState, mapGetters ์™€ ๋‹ค๋ฅธ ์ ์€ methods์— ์ •์˜ํ•ด์คฌ๋‹ค๋Š” ์ ์ด๋‹ค.

import { mapMutations } from 'vuex'

methods: {
  // Vuex ์˜ Mutations ๋ฉ”์„œ๋“œ ๋ช…๊ณผ App.vue ๋ฉ”์„œ๋“œ ๋ช…์ด ๋™์ผํ•  ๋•Œ [] ์‚ฌ์šฉ
  ...mapMutations([
    'addCounter'
  ]),
  // Vuex ์˜ Mutations ๋ฉ”์„œ๋“œ ๋ช…๊ณผ App.vue ๋ฉ”์„œ๋“œ ๋ช…์„ ๋‹ค๋ฅด๊ฒŒ ๋งค์นญํ•  ๋•Œ {} ์‚ฌ์šฉ
  ...mapMutations({
    addCounter: 'addCounter' // ์•ž addCounter ๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”์„œ๋“œ๋ฅผ, ๋’ค addCounter ๋Š” Vuex ์˜ Mutations ๋ฅผ ์˜๋ฏธ
  })
}

mapMutations๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ์จ this.$store.commit('addCounter')๋ฅผ this.addCounter ๋กœ๋งŒ ์“ธ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ• actions

mutations๋Š” ๋™๊ธฐ์  ๋ณ€์ด๋ฅผ ๋‹ค๋ฃฌ๋‹ค๊ณ  ํ•˜์˜€๋‹ค.
actions๋Š” ๊ทธ์™€ ๋ฐ˜๋Œ€๋กœ, ๋น„๋™๊ธฐ์  ๋ณ€์ด๋ฅผ ๋‹ค๋ฃจ๋Š” ์†์„ฑ์ด๋‹ค.

์ฃผ๋กœ setTimeout()์ด๋‚˜ ์„œ๋ฒ„์™€์˜ http ํ†ต์‹  ์ฒ˜๋ฆฌ์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„์˜ฌ ํƒ€์ด๋ฐ์ด ์˜ˆ์ธก๋˜์ง€ ์•Š๋Š” ๋กœ์ง์„ actions์— ์„ ์–ธํ•œ๋‹ค.

mutations์—์„œ ์ƒํƒœ์˜ ๋ณ€์ด๋ฅผ ์ถ”์ ํ•˜๊ธฐ์œ„ํ•ด commit์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค.
actions ์—ญ์‹œ ๋น„๋™๊ธฐ์  ์ƒํƒœ๋ฅผ ์ถ”์ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— commit์„ ์‚ฌ์šฉํ•œ๋‹ค.
๊ฒฐ๊ตญ actions๋Š” ์ •๋ฆฌํ•˜์ž๋ฉด mutations์˜ ๋ฉ”์†Œ๋“œ๋ฅผ actions์— commit์œผ๋กœ ํ˜ธ์ถœํ•˜์—ฌ ๋น„๋™๊ธฐ ๊ด€๋ฆฌ๋ฅผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ดํŽด๋ณด์ž.

export const store = new Vuex.Store({
  // ...
  mutations: {
    addCounter: function (state, payload) {
      return state.counter++;
    }
  },
  actions: {
    addCounter: function (context) {
      return context.commit('addCounter');
    }
  }
});

/src/store.js

 

actions์—์„œ commit์œผ๋กœ mutations์˜ ๋ฉ”์†Œ๋“œ์ธ addCounter๋ฅผ ํ˜ธ์ถœํ•œ ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
์—ฌ๊ธฐ์„œ ์ฃผ๋ชฉํ•ด์•ผํ•  ๊ฒƒ์€ context ์ด๋‹ค. mutations๋‚˜ getters๋Š” state๋‚˜ getters, ๋ฅผ ๋ฐ›์•„์™”์—ˆ๋Š”๋ฐ(ํ˜น์€ ์ „๋‹ฌ์ธ์ž payload), ์ด context๋Š” ๋ฌด์—‡์ผ๊นŒ?

console.log(context)

์ฝ˜์†”์— context๋ฅผ ์ฐ์–ด๋ณด๋‹ˆ, state์™€ getters๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•œ Object ์ž„์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
์ด Object ๋Š” ํ˜„์žฌ ์ €์žฅ์†Œ(store) ์ธ์Šคํ„ด์Šค์˜ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ/ํ”„๋กœํผํ‹ฐ ์„ธํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Vuex ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด์ด๋‹ค.
context.getters, context.state๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์จ์ฃผ์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

addCounter: function ({commit}) {
      return commit('addCounter');
    }

๋‹ค์Œ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ methods์—์„œ actions ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

 methods: {
            increaseCnt() {
                this.$store.dispatch('addCounter');
            }
        },

Conter.vue

 

mutations์—์„  ์ปดํฌ๋„ŒํŠธ methods์—์„œ commit์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, actions๋Š” dispatch๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
mutations์€ ์ถ”์  ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ณ€์ด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด commit์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด commit์€ ์‚ฌ์šฉํ•˜๋Š” ์ฆ‰์‹œ ์ƒํƒœ ๋ณ€์ด๊ฐ€ ์‹คํ–‰๋œ๋‹ค (๋™๊ธฐ์ )
dispatch๋Š” ์ด๋Ÿฌํ•œ commit์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒํ•œ๋‹ค.
action๋‚ด์— ์ •์˜๋œ commit์˜ ํ˜ธ์ถœ ์‹œ๊ธฐ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ง€์ •ํ•˜๋ฏ€๋กœ์จ ๋ง์ด๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ดํŽด๋ด…์‹œ๋‹ค.

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

/src/store.js

 

methods: {
    increaseCnt() {
        this.$store.dispatch('incrementAsync');
    }
}

Counter.vue

 

Counter ์ปดํฌ๋„ŒํŠธ์—์„œ dispatch ๋ฅผ ํ†ตํ•ด actions์˜ incrementAsync ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.
incrementAsync ๋ฉ”์†Œ๋“œ ๋‚ด๋ฅผ ์‚ดํŽด๋ณด๋‹ˆ,
setTimeout์„ ํ†ตํ•ด ๋น„๋™๊ธฐ์ ์œผ๋กœ commit์ด ํ˜ธ์ถœ๋˜๊ณ  ์žˆ์—ˆ๋‹ค.
์ด๋กœ์จ ๋น„๋™๊ธฐ์  ์ƒํƒœ ๋ณ€์ด๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ด๋‹ค.
๋‹จ์ˆœํžˆ dispatch๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๊ณ  ๋น„๋™๊ธฐ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ actions ๋ฉ”์†Œ๋“œ ๋‚ด์— ๋น„๋™๊ธฐ์ ์œผ๋กœ commit์„ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— actions๊ฐ€ ๋น„๋™๊ธฐ์  ๋กœ์ง์„ ๋‹ค๋ฃฌ๋‹ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
๊ฒฐ๊ตญ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด actions๋Š” mutations + commit์˜ ์งฌ๋ฝ•์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค

actions๋Š” mutations ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ „๋‹ฌ์ธ์ž๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ ,
type์†์„ฑ์„ ํฌํ•จํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ›์„์ˆ˜๋„ ์žˆ๋‹ค.

// ํŽ˜์ด๋กœ๋“œ(์ „๋‹ฌ์ธ์ž)์™€ ํ•จ๊ป˜ ๋””์ŠคํŒจ์น˜
store.dispatch('incrementAsync', {
  amount: 10
})

// type์†์„ฑ์„ ํฌํ•จํ•œ ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ๋””์ŠคํŒจ์น˜
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

Promise/then, async/await

actions๋Š” ๋น„๋™๊ธฐ์  ๋กœ์ง์„ ๋‹ค๋ฃฌ๋‹ค๊ณ  ํ–ˆ๋‹ค.
์•ก์…˜์ด ์™„๋ฃŒ๋œ ํ›„์— ๋‹ค์Œ ์ƒํƒœ๋ณ€์ด๊ฐ€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
์šฐ๋ฆฌ๋Š” ๋ณดํ†ต ์–ธ์ œ ๋๋‚ ์ง€ ๋ชจ๋ฅด๋Š” ํ”„๋กœ์„ธ์Šค์˜ ๋‹ค์Œ ํ–‰์œ„๋ฅผ ์œ„ํ•ด Promise/then, async/await๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด์ž

 

Promise/then

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

/src/store.js

 

store.dispatch('actionA').then(() => {
  // ...
})

/src/components/Counter.vue

 

๋˜๋Š”,

actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

/src/store.js

 

async/awiat

// getData() ๋ฐ getOtherData()๊ฐ€ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •
actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // actionA๊ฐ€ ๋๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆผ
    commit('gotOtherData', await getOtherData())
  }
}

mapActions

actions ์—ญ์‹œ this.$store.dispatch('xxx')์˜ ๋ฐ˜๋ณต์„ ๋ง‰๊ธฐ ์œ„ํ•ด mapActions ๋ผ๋Š” ํ—ฌํผ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // this.increment()์„ this.$store.dispatch('increment')์— ๋งคํ•‘

      // mapActions๋Š” ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ง€์›
      'incrementBy' // this.incrementBy(amount)๋ฅผ this.$store.dispatch('incrementBy', amount)์— ๋งคํ•‘
    ]),
    ...mapActions({
      add: 'increment' // this.add()์„ this.$store.dispatch('increment')์— ๋งคํ•‘
    })
  }
}

๐Ÿ• moodules

์ €์žฅ์†Œ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์ง€๋ฉด ๊ด€๋ฆฌ๊ฐ€ ํž˜๋“ค์–ด์งˆ ์ˆ˜๋„ ์žˆ๋‹ค.
๊ทธ ๋•Œ, ์šฐ๋ฆฐ ์ €์žฅ์†Œ๋ฅผ ๋ชจ๋“ˆํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ฐ๊ฐ์˜ state, mutations, getters ๋“ฑ์„ ํฌํ•จํ•˜๋Š” ์ €์žฅ์†Œ ์—ฌ๋Ÿฌ๊ฐœ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

๐Ÿš€ ๋ชจ๋“ˆํ™”๋ž€?
ํŠน์ • ๊ธฐ์ค€์„ ๋‘๊ณ , ๊ทธ ๊ธฐ์ค€์— ๋”ฐ๋ผ ๋ฆฌ์†Œ์Šค๋ฅผ ๋‹จ์œ„๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ๋˜‘๊ฐ™์€ ๋ฉ”์†Œ๋“œ A ๋ฅผ ์—ฌ๋Ÿฌ ํŒŒ์ผ์—์„œ ์“ฐ๊ณ  ์žˆ๋‹ค๊ณ  ํ•˜์ž.
์ด A ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, A ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉ ์ค‘์ธ ๋ชจ๋“  ํŒŒ์ผ์— ๊ฐ€์„œ ์ผ์ผ์ด ์ˆ˜์ •์„ ํ•ด์ค˜์•ผํ•œ๋‹ค.
A ๋ฉ”์†Œ๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๊ต‰์žฅํžˆ ์–ด๋ ค์›Œ์ง„๋‹ค. ์ด ๋•Œ ์šฐ๋ฆฐ ๋ชจ๋“ˆํ™”๋ฅผ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
A ๋ฉ”์†Œ๋“œ๋ฅผ Util.js ๋”ฐ์œ„์˜ ๊ณต์šฉํ™” ํŒŒ์ผ์— ํ•œ๋ฒˆ๋งŒ ์ •์˜ํ•œ ํ›„, A ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด Util.js์˜ A ๋ฉ”์†Œ๋“œ๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
ํ•œ๋งˆ๋””๋กœ ์–ด๋–ค ๋ฆฌ์†Œ์Šค(์—ฌ๊ธฐ์„  A ๋ฉ”์†Œ๋“œ)๋ฅผ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
์ €์žฅ์†Œ์˜ ๋ชจ๋“ˆํ™” ๊ฐ™์€ ๊ฒฝ์šฐ,
state, getters, mutataions์˜ ํฌ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์ปค์ ธ์„œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ €์žฅ์†Œ๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ๋ฌด๋ฆฌ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค.
๋•Œ๋ฌธ์— ์–ด๋–ค ์šฐ๋ฆฐ ๊ธฐ์ค€์„ ๋‘๊ณ  ์ €์žฅ์†Œ๋ฅผ ์ชผ๊ฐ ๋’ค, ํ•„์š”์‹œ์—๋งŒ ์ชผ๊ฐ  ์ผ๋ถ€ ์ €์žฅ์†Œ๋งŒ ํ˜ธ์ถœํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์ด๋‹ค
์ด ์—ญ์‹œ ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌํ•œ๋‹ค์˜ ๋ชจ๋“ˆํ™”๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA'์˜ ์ƒํƒœ
store.state.b // -> moduleB'์˜ ์ƒํƒœ

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Store ์ธ์Šคํ„ด์Šค์— modules๋ผ๋Š” ์†์„ฑ์ด ์žˆ๋‹ค.
modules๋Š” ๊ฐ๊ฐ์˜ state, mutations, getters ๋“ฑ์„ ํฌํ•จํ•œ Object๋ฅผ ๋‹ด๊ณ  ์žˆ๋‹ค.
์ €์žฅ์†Œ๋ฅผ ์ชผ๊ฐœ์–ด ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์˜ˆ์ œ๋กœ ๋ดค์—ˆ๋˜ getters์™€ mutations์˜ ์ฒซ๋ฒˆ์งธ ์ธ์ž state๋Š” ๋ชจ๋“ˆํ™” ๋˜์—ˆ์„ ๋•Œ,
๊ฐ ๋ชจ๋“ˆ์˜ ์ง€์—ญ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.
actions์˜ context์—์„œ๋„ context.state๋Š” ์ง€์—ญ ์ƒํƒœ์ด๋‹ค.
๋ฃจํŠธ์˜ ์ƒํƒœ๋Š” context.rootState๋กœ ํ‘œ์‹œ๋œ๋‹ค. rootState๋Š” getters์˜ ์„ธ๋ฒˆ์งธ ์ „๋‹ฌ์ธ์ž๋กœ ๋…ธ์ถœ๋˜๊ธฐ๋„ ํ•œ๋‹ค.

// actions
const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

// getters
const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

๋„ค์ž„์ŠคํŽ˜์ด์Šค

๋ชจ๋“ˆ์ด ์—ฌ๋Ÿฌ๊ฐœ ์กด์žฌํ•  ๋•Œ, ๋ชจ๋“ˆ๊ฐ„์˜ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ชจ๋“ˆ ๋‚ด์— ๊ฐ™์€ ์ด๋ฆ„์ด ๊ฐ™์€ state, mutations๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋“ฑ์—์„œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.
์ด๋Ÿฌํ•œ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด Vuex ๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
๋„ค์ž„ ์ŠคํŽ˜์ด์Šค๋Š” ๋ชจ๋“ˆ ๋‚ด์— namespaced: true๋กœ ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ž€, ์ปดํฌ๋„ŒํŠธ์—์„œ store ์š”์†Œ(getters ๋“ฑ)๋ฅผ ํ˜ธ์ถœ ํ•  ๋•Œ, ํ•ด๋‹น store ๋ชจ๋“ˆ์˜ ์ด๋ฆ„์„ ๋ถ™์—ฌ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
์ด ํ˜ธ์ถœ์ด ์–ด๋–ค ์ €์žฅ์†Œ ๋ชจ๋“ˆ์—์„œ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฑด์ง€ ๋ช…์‹œํ•˜์—ฌ ์ถฉ๋Œ์„ ์˜ˆ๋ฐฉํ•˜๋Š” ๊ฒƒ.

 

์˜ˆ์ œ๋กœ ์‚ดํŽด ๋ณด์ž.

export const store = new Vuex.Store({
    modules: {
        moduleA: {
            // namespaced: true,
            state: {
                count: 0
            },
            mutations: {
                addCounter: (state) => {
                    return state.count++;
                }
            }
        },
        moduleB: {
            // namespaced: true,
            state: {
                count: 0
            },
            mutations: {
                addCounter: (state) => {
                    return state.count++;
                }
            }
        },
    },
});

/src/store.js

 

namespaced๋ฅผ ํ™œ์„ฑํ™”ํ•˜์ง€ ์•Š์€ moduleA์™€ moduleB๋ฅผ ์ •์˜ํ•ด์คฌ๋‹ค.
๋‘ ๋ชจ๋“ˆ์€ ๋ชจ๋‘ addCounter๋ผ๋Š” ๊ฐ๊ฐ์˜ mutations๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

A, B ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ๊ฐ ๋งŒ๋“ค์–ด ๊ฐ ์นด์šดํŠธ์™€ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ฒ„ํŠผ์„ ์ถœ๋ ฅํ•ด๋ดค๋‹ค.

<template>
    <div>
        {{ count }}
        <button @click="increaseCnt">+</button>
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.moduleA.count;
            }
        },
        methods: {
            increaseCnt() {
                console.log(this.$store.state.moduleA);
                this.$store.commit('addCounter');
            }
        },
    }
</script>

<style scoped>

</style>

/src/components/A.vue

 

<template>
    <div>
        {{ count }}
        <button @click="increaseCnt">+</button>
    </div>
</template>

<script>
    export default {
        computed: {
            count () {
                return this.$store.state.moduleB.count;
            }
        },
        methods: {
            increaseCnt() {
                this.$store.commit('addCounter');
            }
        },
    }
</script>

<style scoped>

</style>

/src/components/B.vue

 

A, B ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ํ™”๋ฉด์— ์ถœ๋ ฅํ•œ ๊ฒฐ๊ณผ

A.vue๋Š” ๋ถ„๋ช…ํžˆ moduleA์˜ count๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์žˆ๊ณ ,
B.vue๋Š” ๋ถ„๋ช…ํžˆ moduleB์˜ count๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์žˆ๋‹ค.

 

A, B ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ํ™”๋ฉด์— ์ถœ๋ ฅํ•œ ๊ฒฐ๊ณผ

ํ•˜์ง€๋งŒ A์˜ ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ, B ์ปดํฌ๋„ŒํŠธ์˜ ์นด์šดํŠธ๊นŒ์ง€ ํ•จ๊ป˜ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
์„œ๋กœ ๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ์นด์šดํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š”๋ฐ๋„ ๋ง์ด๋‹ค. ๐Ÿ˜ฑ

 

์ด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๋ชจ๋“ˆ ๋‚ด์˜ actions, mutations, getters๋Š” ์—ฌ์ „ํžˆ ์ „์—ญ ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค ์•„๋ž˜์— ๋“ฑ๋ก๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค. ๋ณธ์ธ์ด ์–ด๋–ค ๋ชจ๋“ˆ ์ถœ์‹ ์ธ์ง€ ๋ชจ๋ฅด๋Š” ๊ฒƒ. ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์ด ๋™์ผํ•œ ๋™์ž‘์„ ๋ณด์˜€๋˜ ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๋Š”๊ฒŒ ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค์ด๋‹ค.


namespaced: true์˜ ์ฃผ์„์„ ํ’€์–ด ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ ,
A, B ์ปดํฌ๋„ŒํŠธ์˜ commit์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ด๋ดค๋‹ค.

// A.vue
this.$store.commit('moduleA/addCounter');

// B.vue
this.$store.commit('moduleB/addCounter');

A View์˜ ํ”Œ๋Ÿฌ์Šค ๋ฒ„ํŠผ์„ ์„ธ๋ฒˆ ๋ˆ„๋ฅธ ๊ฒฐ๊ณผ

๋„ค์ž„์ŠคํŽ˜์ด์Šค๋กœ ๋ชจ๋“ˆ์ด ๊ตฌ๋ถ„๋˜์–ด ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ „์—ญ ์ž์‚ฐ ์ ‘๊ทผ

getters ์˜ ์ „๋‹ฌ์ธ์ž ๋ถ€๋ถ„์—์„œ ์ž ๊น ์–ธ๊ธ‰๋์—ˆ๋Š”๋ฐ,
getters์™€ actions๋Š” ๊ฐ๊ฐ ๋””ํดํŠธ ์ธ์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

// getters
someGetter (state, getters, rootState, rootGetters) {
        // ...
    },

// actions (context ์ธ์ž ๋‚ด์— ์žˆ๋Š” ์†์„ฑ๋“ค)
someActions ({ dispatch, commit, getters, rootGetters }) {
        // ...
    }

์ด rootGetters, ํ˜น์€ rootSetters๋ฅผ ํ†ตํ•ด namespaced๊ฐ€ ์ •์˜๋œ ๋ชจ๋“ˆ ๋‚ด์—์„œ ์ „์—ญ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

modules: {
  foo: {
    namespaced: true,

    getters: {
      // `getters`๋Š” ํ•ด๋‹น ๋ชจ๋“ˆ์˜ ์ง€์—ญํ™”๋œ getters
      // getters์˜ 4๋ฒˆ์งธ ์ธ์ž๋ฅผ ํ†ตํ•ด์„œ rootGetters ์‚ฌ์šฉ ๊ฐ€๋Šฅ
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter'
        rootGetters.someOtherGetter // -> 'someOtherGetter'
      },
      someOtherGetter: state => { ... }
    },

    actions: {
      // ๋””์ŠคํŒจ์น˜์™€ ์ปค๋ฐ‹๋„ ํ•ด๋‹น ๋ชจ๋“ˆ์˜ ์ง€์—ญํ™”๋œ ๊ฒƒ
      // ์ „์—ญ ๋””์ŠคํŒจ์น˜/์ปค๋ฐ‹์„ ์œ„ํ•œ `root` ์˜ต์…˜ ์„ค์ • ๊ฐ€๋Šฅ
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },
      someOtherAction (ctx, payload) { ... }
    }
  }
}

/src/store.js

 

์œ„ ์ฝ”๋“œ์˜ root:true ๊ฐ€ ๋ณด์ด๋Š”๊ฐ€?
์ „์—ญ actions์„ dispatch ํ•˜๊ฑฐ๋‚˜ mutations๋ฅผ commit ํ•˜๋ ค๋ฉด
dispatch ์™€ commit ์˜ 3๋ฒˆ์งธ ์ธ์ž์— { root: true } ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค

 

๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ ์ „์—ญ ์•ก์…˜ ๋“ฑ๋ก

๋„ค์ž„ ์ŠคํŽ˜์ด์Šค ๋ชจ๋“ˆ์—์„œ ์ „์—ญ actions๋ฅผ ๋“ฑ๋กํ•˜๋ ค๋ฉด root: true๋ฅผ ํ‘œ์‹œํ•˜๊ณ 
handler ํ•จ์ˆ˜์— actions๋ฅผ ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค.

actions: {
    someOtherAction ({dispatch}) {
      dispatch('someAction')
    }
  },
  modules: {
    foo: {
      namespaced: true,

      actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }
    }
  }

/src/store.js

 

์ด๋กœ์จ ์ „์—ญ ์•ก์…˜์ธ someOtherActions์„ ํ˜ธ์ถœํ•˜๋ฉด foo ๋ชจ๋“ˆ์— ์ •์˜๋œ
someAction ์ด ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.

 

ํ—ฌํผ์—์„œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ฐ”์ธ๋”ฉ

ํ—ฌํผ์—๋Š” mapState, mapGetters, mapActions, mapMutations ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค.
ํ—ฌํผ์—์„œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ชจ๋“ˆ์„ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์กฐ๊ธˆ ์žฅํ™ฉํ•˜๊ฒŒ ๋ ์ˆ˜ ์žˆ๋‹ค.

computed: {
  ...mapState({
    a: state => state.some.nested.module.a,
    b: state => state.some.nested.module.b
  })
},
methods: {
  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])
}

์ค‘์ฒฉ๋œ ๋ชจ๋“ˆ์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋˜๊ณ  ๊ธธ์–ด์ง„๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
์ด๋Š” ๋ชจ๋“ˆ์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋ฌธ์ž์—ด์„ ํ—ฌํผ์˜ ์ฒซ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ ๊ฐ„๊ฒฐํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])
}

๋˜ํ•œ createNamespacedHelpers๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ํ—ฌํผ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')

export default {
  computed: {
    // `some/nested/module`์—์„œ ์ฐพ์Œ
    ...mapState({
      a: state => state.a,
      b: state => state.b
    })
  },
  methods: {
    // `some/nested/module`์—์„œ ์ฐพ์Œ
    ...mapActions([
      'foo',
      'bar'
    ])
  }
}

 

๋™์  ๋ชจ๋“ˆ ๋“ฑ๋ก

store.registerModule ๋ฉ”์†Œ๋“œ๋กœ ์ €์žฅ์†Œ(store)๊ฐ€ ๋“ฑ๋ก๋œ ํ›„์—๋„ ๋ชจ๋“ˆ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

store.registerModule('myModule', {
  // ...
})

// `nested/myModule` ์ค‘์ฒฉ ๋ชจ๋“ˆ ๋“ฑ๋ก
store.registerModule(['nested', 'myModule'], {
  // ...
})

store.unregisterModule(moduleName) ๋กœ ๋™์ ์œผ๋กœ ๋“ฑ๋ก๋œ ๋ชจ๋“ˆ์„ ์ œ๊ฑฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
์ •์  ๋ชจ๋“ˆ์€ ์ œ๊ฑฐํ•  ์ˆ˜ ์—†๋‹ค


์ด๋กœ์จ Vuex ์— ๋Œ€ํ•œ ๊ฐœ๋…๊ณผ ์˜ˆ์ œ์— ๋Œ€ํ•ด ๋ชจ๋‘ ์•Œ์•„๋ดค๋‹ค!

๋Œ“๊ธ€๊ณผ ํ”ผ๋“œ๋ฐฑ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค...

 

 

๋”๋ณด๊ธฐ

Seize the day!

Spring MVC | Spring Boot | Spring Security | Mysql | Oracle | PostgreSQL | Vue.js | Nuxt.js | React.js | TypeScript | JSP | Frontend | Backend | Full Stack | ์ž๊ธฐ๊ณ„๋ฐœ | ๋ฏธ๋ผํด ๋ชจ๋‹ | ์ผ์ƒ