FE/Vue.js

[ Vue.js ] Vuex

지니엠 2024. 5. 23. 15:31

 

 

 

 

 

 

 

 

Vuex란?

무수히 많은 컴포넌트의 데이터를 효율적으로 관리하기 위한 상태관리 패턴이자 라이브러리

▷ React의 Flux패턴에서 기인

▷ Vue.js 중고급 개발자로 성장하기 위한 필수 관문

 

 

 

 

컴포넌트의 개수가 많아질수록 데이터전달이 어려워지는데

이벤트 버스로 해결한다고 하면?

//Login.vue
eventBus.$emit('fetch', loginInfo);

// List.vue
eventBus.$on('display', data => this.displayOnScreen(data));

// Chart.vue
eventBus.$emit('refreshData',chartData);

어디서 이벤트를 보냈는지, 어디서 받았는지를 알기가 어렵다

컴포넌트 간 데이터 전달이 명시적이지 않다!

 

 


 

 

Flux - Unidirectional data flow

MVC패턴의 복잡한 데이터 흐름 문제를 해결하는 개발 패턴

 

Action >> Dispatcher >> Model >> View

모든 데이터 흐름이 한방향(단방향)

 

프레임워크 자체(패턴)에서 데이터의 흐름을 정형화 시켜서 향후에 발생할 수 있는 문제점들을 

미리 예측해서 방지하는 것! 

 

1. action: 화면에서 발생하는 이벤트 도는 사용자의 입력

2. dispatcher : 데이터를 변경하는 방법, 메서드(model을 바꾸기 위한 역할)

3. model : 화면에 표시할 데이터

4. view : 사용자에게 비춰지는 화면

 

+

MVC 패턴

Controller -- >> Model << -- >> View

양방향으로 이루어진다

기능 추가 및 변경에 따라 생기는 문제점을 예측할 수 없다.

앱이 복잡해지면서 생기는 업데이트루프(ex 페이스북 채팅화면)

 

 


Vuex로 해결할 수 있는 문제

 

1. MVC패턴에서 발생하는 구조적 오류2. 컴포넌트 간 데이터 전달 명시3. 여러개의 컴포넌트에서 같은 데이터를 업데이트 할 때 동기화 문제

 

 

 

Vuex 컨셉

State : 컴포넌트 간에 공유하는 데이터 data( )View : 데이터를 표시하는 화면 templateAction : 사용자의 입력에 따라데이터를 변경하는 methods

 

view(화면)에서 -> 버튼을 클릭하면(v-on) action을 실행시킨다 -> 데이터를 변경(state)

 

 

Vuex 구조

컴포넌트 -> 비동기 로직 -> 동기 로직 -> 상태

 


 

Vuex 설치하기( vue3 )

npm install vuex@next --save

 

 

강의내용이랑 맞추기 위해 지금부터 vue2로 진행 -> vuex 버전도 vue2에 맞게 설치해야 한다 !

 

package.json

"dependencies": {
    "core-js": "^3.8.3",
    "vue": "^2.6.14",
    "vuex": "^3.6.2"
  },

설치된거 확인하고, 

src > store > store.js 파일 생성하고 vuex를 등록해주자.

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

Vue.use(Vuex);
//use는 Vue의 플러그인 기능 글로벌 functionality를 추가하고싶을때 사용하는것

export const store = new Vuex.Store({
  //
});

코어 라이브러리를 등록하고(import) 

use는 공식문서에서도 써있는 형태인데, 모든 영역에 특정 기능을 추가하고 싶을때 사용하는 것

 

이제 main.js에 들고와서 등록을 해준다.

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

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

store 라이브러리에 접근하고(import), store변수까지 등록해주면 된다.

 


 

Vuex 기술 요소

state : 여러 컴포넌트에 공유되는 데이터 data

getters : 연산된 state 값을 접근하는 속성 computed

mutations : state값을 변경하는 이벤트 로직 메서드 methods

actions : 비동기 처리 로직을 선언하는 메서드 async methods

 

state 

// Vue
data: { 
	message : 'Hello Vue.js!'
}

// Vuex
state: {
	message: 'Hello Vue.js'
}
<!-- Vue -->
<p>{{ message }}</p>

<!-- Vuex -->
<p>{{ this.$store.state.message }}</p>

this.$store > vue use.vuex 전역 플러그인을 추가해주었기 때문에 접근이 가능한거다

 

 

getters

//store.js
state: {
	num: 10
},
getters: {
	getNumber(state){
    	return state.num;
    },
   	doubleNumber(state){
    	return state.num * 2;
    }
}
<p>{{ this.$store.getters.getNumber }}</p>
<p>{{ this.$store.getters.doubleNumber }}</p>

 

 

mutations

// store.js
state: {num : 10},
mutations: {
 	printNumbers(state){
    	return state.num
    },
    sumNumbers(state, anotherNum) {
    	return state.num + anotherNum;
    }
}

// App.vue
this.$store.commit('printNumbers');
this.$store.commit('sumNumbers', 20);

 

mutationas의 commit() 형식 >>  state를 변경하기 위해 mutations를 동작시킬 떄 인자(payload)를 전달할 수 있음

// store.js
state: { storeNum : 10},
mutations: {
	modifyState(state, payload){
    	console.log(payload.str);
        return state.storeNum += payload.num;
    }    
}

// App.vue
this.$store.commit('modifyState',{
	str: 'passed from payload',
    num: 20
});

state의 값을 수정할수 있는건 mutations!

 

state는 왜 직접변경하지 않고 mutations으로 변경할까?

mutations을 거치지 않으면 어느 컴포넌트에서 어떤시점에 해당 state를 변경했는지 추적하기가 어렵다.

>> mutations을 통해 변경하면 vue 개발자 도구에서도 추적할 수 있다.

뷰의 반응성을 거스르지 않게 명시적으로 상태변화를 수행할 수 있다.

 

 

 

actions

// store.js
state: {
	num: 10
},
mutations: {
doubleNumber(state){
	state.num * 2;
   }
},
actions: {
	delayDoubleNumber(context){ // context로 store의 메서드와 속성 접근
    	context.commit('doubleNumber');
    }
}
// App.vue
this.$store.dispatch('delayDoubleNumber');

 

비동기 코드 예제 ( setTimeount() ) 

// store.js
mutations: {
	addCounter(state){
    	state.counter++
   },
},
actions: {
	delayedAddCounter(context){
    	setTimeOut(( => context.commit('addCounter'), 2000);
    }
}

//App.vue
methods:{
	incrementCounter(){
    	this.$store.dispatch('delayedAddCounter');
    }
}

액션은 디스패치라는 API를 호출해서 액션을 실행시킨다.

 

왜 비동기 처리 로직은 actions에 선언해야 할까?

언제 어느 컴포넌트에서 해당 state를 호출하고, 변경했는지 확인하기가 어렵다

>> state값의 변화를 추적하기 어렵기 떄문에 mutations속성에는 동기 처리 로직만 넣어야 한다.