๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โญ Personal_Study/Vue

Vuex

by ํฌ์ŠคํŠธ์‰์ดํฌ 2022. 11. 14.

Vuex

State Management

State Management(์ƒํƒœ ๊ด€๋ฆฌ) ๊ฐœ์š”

โœ” ์ƒํƒœ(state): ํ˜„์žฌ์— ๋Œ€ํ•œ ์ •๋ณด(data)
โœ” Web Application์˜ ์ƒํƒœ: ํ˜„์žฌ App์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” data
โœ” ๊ฐ component๋Š” ๋…๋ฆฝ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ฐ์˜ ์ƒํƒœ(data๋ฅผ ๊ฐ€์ง„๋‹ค)
โœ” ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ component๋“ค์ด ๋ชจ์—ฌ ํ•˜๋‚˜์˜ App์„ ๊ตฌ์„ฑํ•˜๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ component๊ฐ€ ๊ฐ™์€ ์ƒํƒœ(data)๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค!

Pass Props & Emit Event

โœ” ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ์ง๊ด€์ ์œผ๋กœ ํŒŒ์•… ๊ฐ€๋Šฅํ•˜๋‹ค
โœ” ๊ทธ๋Ÿฌ๋‚˜ component์˜ ์ค‘์ฒฉ์ด ๊นŠ์–ด์ง€๋ฉด ๋ฐ์ดํ„ฐ์˜ ์ „๋‹ฌ์ด ์–ด๋ ค์›Œ์ง„๋‹ค๋Š” ๋‹จ์ 

Centralized Store

โœ” ์ค‘์•™ ์ €์žฅ์†Œ(store)์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ์•„์„œ ์ƒํƒœ ๊ด€๋ฆฌ
โœ” component์˜ ๊ณ„์ธต์— ์ƒ๊ด€์—†์ด ์ค‘์•™ ์ €์žฅ์†Œ์— ์ ‘๊ทผํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
โœ” ์ค‘์•™ ์ €์žฅ์†Œ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ฐ๊ฐ์˜ component๋Š” ํ•ด๋‹น ๋ฐ์ดํ„ฐ์˜ ๋ณ€ํ™”์— ๋ฐ˜์‘ํ•˜์—ฌ ์ƒˆ๋กœ ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜์˜
โœ” ๊ทœ๋ชจ๊ฐ€ ํฌ๊ฑฐ๋‚˜ ์ปดํฌ๋„ŒํŠธ ์ค‘์ฒฉ์ด ๊นŠ์€ ํ”„๋กœ์ ํŠธ์˜ ๊ด€๋ฆฌ๊ฐ€ ๋งค์šฐ ํŽธ๋ฆฌ

Vuex ์‹œ์ž‘ํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

$ vue create vuex-app

$ cd vuex-app

$ vue add vuex

index.js

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

Vue.use(Vuex);

export default new Vuex.Store({
  // ๊ธฐ์กด vue instance์˜ data
  state: {},

  // ๊ธฐ์กด vue instance์˜ computed
  getters: {},

  // ๊ธฐ์กด vue instance์˜ methods
  mutations: {},
  actions: {},

  modules: {},
});

1. state

โœ” vue ์ธ์Šคํ„ด์Šค์˜ data์— ํ•ด๋‹น
โœ” ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๋ชจ๋“  ์ƒํƒœ ์ •๋ณด
โœ” state์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€ํ™”ํ•˜๋ฉด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋Š” component๋„ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๋ Œ๋”๋ง
โœ” $store.state๋กœ state ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ

2. mutations

โœ” ์‹ค์ œ๋กœ state๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•
โœ” Mutations์—์„œ ํ˜ธ์ถœ๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๋™๊ธฐ์ ์ด์–ด์•ผํ•จ

  • ๋น„๋™๊ธฐ ๋กœ์ง์œผ๋กœ mutations๋ฅผ ์‚ฌ์šฉํ•ด์„œ state๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ, state์˜ ๋ณ€ํ™”๋ฅผ ์‹œ๊ธฐ๋ฅผ ํŠน์ •ํ•  ์ˆ˜ ์—†๋‹ค!

โœ” ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ state๋ฅผ ๋ฐ›์œผ๋ฉฐ, component ํ˜น์€ Actions์—์„œ commit() ๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœ๋œ๋‹ค

3. Actions

โœ” mutations์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์Œ
โœ” state๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  commit() ๋ฉ”์„œ๋“œ๋กœ mutations๋ฅผ ํ˜ธ์ถœํ•ด์„œ state๋ฅผ ๋ณ€๊ฒฝ
โœ” context ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›์œผ๋ฉฐ, ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด store.js์˜ ๋ชจ๋“  ์š”์†Œ์™€ ๋ฉ”์„œ๋“œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค (stated๋„ ์ง์ ‘ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๋ณ€๊ฒฝ ํ•˜๋ฉด ์•ˆ๋œ๋‹ค!)
โœ” component์—์„œ dispatch() ๋ฉ”์„œ๋“œ์— ์˜ํ•ด ํ˜ธ์ถœ

Mutations & Actions

โœ” Mutations: state๋ฅผ ๋ณ€๊ฒฝ
โœ” Actions: state ๋ณ€๊ฒฝ์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ๋กœ์ง

4. Getters

โœ” vue ์ธ์Šคํ„ด์Šค์˜ computed์— ํ•ด๋‹น
โœ” state๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ์–ป๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉ
โœ” computed์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ getters์˜ ๊ฒฐ๊ณผ๋Š” ์บ์‹œ(cache)๋˜๋ฉฐ, ์ข…์†๋œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์—๋งŒ ์žฌ๊ณ„์‚ฐ๋œ๋‹ค.
โœ” getters์—์„œ ๊ณ„์‚ฐ๋œ ๊ฐ’์€ state์— ์˜ํ–ฅ x
โœ” ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ state, ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ getter

๊ทธ๋ ‡๋‹ค๋ฉด ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ Vuex์—์„œ ๊ด€๋ฆฌํ• ๊นŒ?

โœ” Vuex์—์„œ๋„ ์—ฌ์ „ํžˆ pass props, emit event๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ ๊ด€๋ฆฌ ํ•  ์ˆ˜ ์žˆ์Œ
โœ” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”

์ •๋ฆฌ

โœ” component์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„

  • component => (actions) => mutations => state

โœ” component์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„

  • state => (getters) => component

Vuex ์‹ค์Šต

๊ฐ์ฒด ์ถ•์•ฝํ˜• ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

// before
const obj1 = {
  addValue: function (value) {
    return value;
  },
};

// after
const obj2 = {
  addValue(value) {
    return value;
  },
};

state

// store/index.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: "message in store",
  },
  getters: {},
  mutations: {},
  actions: {},
  modules: {},
});
// App.vue
<template>
  <div id="app">
    <h1>{{ $store.state.message }}</h1>
  </div>
</template>

โœ” $store.state๋กœ ๋ฐ”๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅ! ๊ทธ๋Ÿฌ๋‚˜...

<template>
  <div id="app">
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  computed: {
    message() {
      return this.$store.state.message;
    },
  },
};
</script>

โœ” computed์— ์ •์˜ ํ›„ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅ

actions

// App.vue

<template>
  <div id="app">
    <h1>{{ message }}</h1>
    <input type="text" @keyup.enter="changeMessage" v-model="inputData" />
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      inputData: null,
    };
  },
  computed: {
    message() {
      return this.$store.state.message;
    },
  },
  methods: {
    changeMessage() {
      const newMessage = this.inputData;
      // action ํ˜ธ์ถœ
      this.$store.dispatch("changeMessage", newMessage);
    },
  },
};
</script>

โœ” state๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” mutations ํ˜ธ์ถœ
โœ” component์—์„œ dispatch()์— ์˜ํ•ด ํ˜ธ์ถœ๋จ
โœ” dispatch(ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•˜๋Š” actions ํ•จ์ˆ˜, ๋„˜๊ฒจ์ค„ Data)

// store/index.js

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

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    message: "message in store",
  },
  getters: {},
  mutations: {},
  actions: {
    changeMessage(context, newMessage) {
      console.log(context);
      console.log(newMessage);
    },
  },
  modules: {},
});

โœ” actions์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” context

  • context๋Š” store์˜ ์ „๋ฐ˜์ ์ธ ์†์„ฑ์„ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ context.state์™€ context.getters๋ฅผ ํ†ตํ•ด mutations๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅ
  • ๋‹จ, actions์—์„œ state๋ฅผ ์ง์ ‘ ์กฐ์ž‘ x

โœ” actions์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” payload

  • ๋„˜๊ฒจ์ค€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์‚ฌ์šฉ

mutations

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    message: 'message in store'
  },
  getters: {
  },
  mutations: {
    // ๋งˆ์ง€๋ง‰์— ์ง์ ‘์ ์œผ๋กœ state๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ๋•Œ๋ฌธ์—๋ช…์‹œ์ ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ์ƒ์ˆ˜ ํ˜•ํƒœ๋กœ ์ด๋ฆ„ ์ž‘์„ฑ
    CHANGE_MESSAGE(state, newMessage) {
      // console.log(state)
      // console.log(newMessage)

      // state ์กฐ์ž‘
      state.message = newMessage
    }
  },
  actions: {
    changeMessage(context, newMessage) {
      // console.log(context)
      // console.log(newMessage)

      // mutation ํ˜ธ์ถœ
      context.commit('CHANGE_MESSAGE', newMessage)
    }
  },
  modules: {
  }
})

โœ” actions์—์„œ commit()์ด์šฉํ•ด mutations ํ˜ธ์ถœ
โœ” commit(A, B)

  • A: ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•˜๋Š” mutations ํ•จ์ˆ˜
  • B: payload

getters

// store/index.js

export default new Vuex.Store({
  ...
  getters: {
    messageLength(state) {
      return state.message.length
    }
  },
  ...
})

โœ” state๋ฅผ ํ™œ์šฉํ•œ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜
โœ” ์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” state,๋‘๋ฒˆ์งธ ์ธ์ž๋Š” getters(์„ ํƒ)

// App.vue

<template>
  <div id="app">
    <h1>{{ message }}</h1>
    <h2>๋ฌธ์ž์˜ ๊ธธ์ด๋Š” {{ messageLength }}</h2>
    <input type="text" @keyup.enter="changeMessage" v-model="inputData" />
  </div>
</template>

<script>
export default {
  ...
  computed: {
    message() {
      return this.$store.state.message;
    },
    // getters ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
    messageLength() {
      return this.$store.getters.messageLength
    }
  },
  ...
};
</script>

'โญ Personal_Study > Vue' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Vuex ํ™œ์šฉํ•ด Todo SPA ์•ฑ ๋งŒ๋“ค๊ธฐ  (0) 2022.11.15
Lifecycle Hooks  (0) 2022.11.14
Emit Event  (0) 2022.11.13
Pass Props  (0) 2022.11.12
Vue Component  (0) 2022.11.11

๋Œ“๊ธ€