Vuex

바그다드·2023년 11월 15일
0

복잡한 어플리케이션의 컴포넌트들을 효츌적으로 관리하는 라이브러리

  • 무수히 많은 컴포넌트의 데이터를 관리하기 위한 패턴이자 라이브러리
  • React의 Flux 패턴에서 기인함

Flux란?

  • MVC패턴의 복잡한 데이터 흐름 문제를 해결하는 개발 패턴 - Unidirectional data flow
  1. action : 화면에서 발생하는 이벤트나 사용자의 입력
  2. dispatcher : 데이터를 변경하는 방법, 메서드
  3. model : 화면에 표시할 데이터
  4. view : 사용자에게 비춰지는 화면
  • MVC 패턴의 문제점
  1. 기능 추가 및 변경에 따라 생기는 문제점을 예측할 수가 없음
  2. 앱이 복잡해지면서 생기는 업데이트 루프
  • Flux 패턴의 단방향 데이터 흐름
    데이터의 흐름이 여러 갈래로 나뉘지 않고 단방향으로만 처리

vuex로 해결할 수 있는 문제

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

vuex 컨셉

  • state : 컴포넌트 간에 공유하는 데이터
    vue에서 data:{}속성을 뜻함
  • view : 데이터를 표시하는 화면 template부분
  • action : 사용자의 입력에 따라 데이터를 변경하는 methods

Vuex 활용

1. vuex 설치

1. 라이브러리 설치

https://v3.vuex.vuejs.org/kr/installation.html

npm install vuex --save

2. container.js 생성

container를 생성한다

  • vue 2버전과 3버전 각각 등록하는 방법이 다르므로 참고하자(여기서는 vue3로 진행하고 있음)
import {createStore} from 'vuex'

const storage = {
}

// 이건 vue2버전 방식이다
// Store = 첫글자 대문자!!
//export const store = new Vuex.Store({
export default createStore({
    state: {
        testText: 'Learn Vuex',
    }
});

3. vuex 등록

main.js에 vuex를 전역변수로 등록해주자.

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


// use() : 플러그인
// vue를 사용하는 모든 영역에 글로벌 function을 추가하고자 할 때 사용
createApp(App).use(store).mount('#app')

// vue 버전2
// new Vue({
//     el: '#app',
//     store,
//     render: h => h(App)
// });

2. Vuex 속성

  1. state : 여러 컴포넌트에 공유되는 데이터
    기존 vue에서는 data
  2. getters : 연산된 state값을 접근하는 속성
    기존 vue에서는 computed 메서드
  3. mutation : state값을 변경하는 이벤트 로직
    기존 vue에서는 methods
  4. actions : 비동기 처리 로직을 선언하는 메서드
    기존 vue에서는 async methods

1. state(상태)란?

여러 컴포넌트 간에 공유할 데이터를 뜻함

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

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

2. getters란?

state값에 접근하는 속성이자 computed()처럼 미리 연산된 값에 접근할때 사용하는 속성

state: {
	num: 10
}
getters: {
	doubleNumber(stat){
    	return state.num * 2;
    }
}

<p>{{ this.$store.getters.doubleNumber }}</p>

doubleNumber에 접근함으로 이미 연산된 값에 접근할 수 있음

3. mutations란?

  • state값을 변경할 수 있는 유일한 방법이자 메서드를 뜻한다.
  • mutations에 정의된 함수는 commit()으로 동작시킬 수 있다.
// store.js
state: {num: 10},
mutations: {
	// mutation 내의 메서드에는 첫번째 인자로 state가 넘어감
	printNumbers(state){
    	return state.num;
    },
    sumNumbers(state, anotherNum){
    	return state.num + anotherNum;
    }
}

// App.vue
// commit : 인자와 일치하는 mutation 메서드를 실행시킴
this.$store.commit('printNumbers');
this.$store.commit('sumNumbers', 20);
  • mutation내 메서드의 첫번째 파라미터는 state가 온다.
  • mutations를 동작시킬 때 인자(payload)를 함께 전달할 수 있음
// store.js
state: {stateNum: 10},
mutations: {
	sumNumber(state, payload){
    	console.log(payload.str);
        return state.stateNum += payload.num;
    }
}

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

mutations를 사용하는 이유

직접 state를 이용해 값을 변경하지 않고 mutations를 이용해 변경하는걸까?

여러 컴포넌트에서 state를 변경하는 경우 어떤 컴포넌트에서 변경했는지, 어떤 시점에 변경한건지 추적이 어렵다.

vuex는 vue core팀에서 만든 라이브러리로 flux패턴을 vue에 맞춰 구현해놓았기 때문에 mutations를 거치지 않으면 vue의 반응성(directive)이나 명시적 상태 변화를 수행하기 어렵기 때문에 state의 값을 변경하려면 mutations를 활용해야 한다.

  • mutations는 state의 값을 변경하기 위해서 사용된다.

4. actions란?

  • 비동기 처리 로직을 선언하는 메서드로 비동기 로직으로 담당하는 mutations이다.
  • 데이터 요청, Promise, async와 같은 비동기 처리는 모두 actions에 선언한다.
// store.js
state: {
	num: 10
},
mutations: {
	doubleNumber(state){
    	state.num * 2;
    }
},
actions: {
	// context로 store의 메서드와 속성에 접근
	delayDoubleNumber(context){ 
    	context.commit('doubleNumber');
    }
}

// App.vue
this.$store.dispatch('delayDoubleNumber');
  • dispatch('메서드 이름')를 이용해 actions를 호출함
  • dispatch -> delayDoubleNumber -> doubleNumber -> state

actions 코드 예제1

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

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

actions 코드 예제2 - axios

//store.js
mutations: {
	setData(state, fetchedData){
    	state.product = fetchedData;
    }
},
actions: {
	fetchedData(context){
    	return axios.get('http://domain.com/products/1')
        	.then(response => context.commit('setData', response));
    }
}

// App.vue
methods: {
	getProduct() {
    	this.$store.dispatch('fetchProductData');
    }
}
  • domain.com과의 비동기 통신으로 값을 받아와(response) setData에 넘기고, state.product에 저장하는 로직

비동기 로직을 actions에 선언하는 이유

  • 비동기로 처리해 state를 언제 호출하고 변경했는지 확인하기 어렵기 때문이다.
  • 위의 그림과 같이 하나의 state에 각각 다른 컴포넌트에서 다른 시간에 접근해 값을 변경하면 이를 추적하기 어렵다.

따라서 actions에는 비동기 처리 로직을 선언하고, mutations에는 동기 처리 로직을 선언해야 한다.

profile
꾸준히 하자!

0개의 댓글