# 16. Vuex

## Vuex 란 ?

글로벌하게 state 를 관리할 수 있도록 도와주는 상태관리 라이브러리입니다.

### 왜 vuex 가 필요한가요 ?&#x20;

#### 1. 형제끼리의 state 교환이 불가능합니다

일반적인 vue state 의 흐름으로는 형제끼리의 데이터 교환이 불가능합니다. \
그렇기 때문에 이런 상황에는 두 컴포넌트를 감싸고 있는 부모 컴포넌트로 state 를 올려서 사용하게됩니다.

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-Llz696Q7z77Jf-xTHUS%2F-Llz8r4F2Rl58p1ib_1q%2Fimage.png?alt=media\&token=a968e619-9c85-41f7-ad5c-ff81d9529353)

#### 2. props 의 깊이가 깊어질 경우&#x20;

1번에서 살펴본것처럼 state 를 부모로 올렸더라도 해당 데이터를 원하는 컴포넌트의 깊이가 깊어질수록 props 를 내려주는것이 힘들고 복잡해집니다.

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-Llz696Q7z77Jf-xTHUS%2F-Llz9IATbXtxTvGxRUlI%2Fimage.png?alt=media\&token=c82d1d3c-3d5a-4eea-81ed-eaa573f3f846)

#### 3. 액션에 따라 동시에 바뀌는 컴포넌트들

버튼이 클릭되었을때 여러 컴포넌트들에 동시에 영향을 주는 경우가 있다면 vuex 도입을 고려해봄직합니다.

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-Llz696Q7z77Jf-xTHUS%2F-LlzBIsvXBQ-HyeqCXlB%2Fimage.png?alt=media\&token=48819878-b5d2-461c-ae4d-2ecee762a287)

###

## 실습

> (예제는 [이전의](https://simplevue.gitbook.io/intro/02.-component#undefined-3) 초기 구성되었던 환경에서 시작합니다.)

vuex 의 흐름은 아래와 같습니다. 크게 state, getters, mutations, actions 로 나뉩니다.

* state: 관리할 상태 값들
* getters: 밖으로 내보낼 값들 (실제 컴포넌트에서 가져가 사용할 값들)
* mutations: 실제 state 가 변화되는곳&#x20;
* actions: mutations 을 일으키는곳 (state 변화 x)

컴포넌트에서 state 를 가져오기 위해서는 getters 를 이용하고 state 에 변화를 주기 위해서는 actions 를 이용합니다.

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-LlzC68Sfkv0fflWZIz5%2F-LlzCOulhKdSF7-uBgEc%2Fimage.png?alt=media\&token=0fa4ab2b-09e4-4e74-9cb1-1554220f5067)

#### 먼저 vuex 를 설치합니다

```bash
$ npm i --save vuex 
```

#### Store 정의&#x20;

```javascript
// src/store.js

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

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    // 글로벌로 관리될 상태 값 
    counter: 0
  },
  getters: {
    // 데이터에 변화를 줄 순 없다.
    counter: state => state.counter
  },
  mutations: {
    // 실제 데이터 변화가 일어나는 곳
    increment: state => (state.counter += 1),
    decrement: state => (state.counter -= 1)
  },
  actions: {
    // mutaion 을 일을키위한 행동, 컴포넌트에서는 actions 를 사용한다
    addCounter: context => context.commit("increment"),
    subCounter: context => context.commit("decrement")
  }
});

```

vue 는 아직 vuex 의 존재를 모르기 때문에 vue 객체가 생성될때 해당 store 의 존재를 알려줘야합니다.

```javascript
// main.js

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");
```

#### 컴포넌트 구성

왼쪽 컴포넌트를 -, + 버튼을 노출하고 오른쪽 컴포넌트에는 현재 값을 표현하도록하고 싶습니다. \
왼쪽 컴포넌트에서는 버튼을 누를때마다 actions 을 일으켜 해당 mutation 을 일으킵니다.\
오른쪽 컴포넌트에서는 getter 를 이용하여 counter 값을 노출합니다.

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-LlzC68Sfkv0fflWZIz5%2F-LlzEPpfOA3MZlvjxRON%2Fimage.png?alt=media\&token=a444e081-63f4-4d43-94ed-dcb42fab5dda)

먼저 Left 컴포넌트를 준비합니다.\
vuex 의 action 에 접근하기 위해서는 vuex 에서 제공해주는 mapActions 라는 함수를 이용합니다.

```javascript
// components/Left.vue

<template>
  <div>
    <button @click="subCounter">-</button> // vuex 의 action 을 일으킵니다
    <button @click="addCounter">+</button>
  </div>
</template>

<script>
import { mapActions } from "vuex";

export default {
  methods: {
    ...mapActions(["addCounter", "subCounter"])
  }
};
</script>

<style>
</style>

```

다음은 Right 컴포넌트를 준비합니다.\
getter 에 접근하기 위해서는 vuex 에서 제공해주는 mapGetters 를 이용합니다.

```javascript
// components/Right.vue 

<template>
  <div>value: {{ counter }}</div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
  computed: {
    ...mapGetters(["counter"])
  }
};
</script>

<style>
</style>

```

마지막으로 App.vue 에서 컴포넌트들을 불러옵니다.

```javascript
// App.vue

<template>
  <div>
    <Left />
    <Right />
  </div>
</template>

<script>
import Left from "./components/Left";
import Right from "./components/Right";

export default {
  components: {
    Left,
    Right
  }
};
</script>

<style>
</style>

```

![](https://3068925918-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYGyJlfT4aHSW1TgIhy%2F-LlzC68Sfkv0fflWZIz5%2F-LlzGugIL7QcRla2A3oc%2Fggggg.gif?alt=media\&token=35597fb7-00f4-4996-bb4b-ee912aa8f356)
