기록/FRONTEND

[Vue] Vuex

5월._. 2022. 5. 28.
728x90

1. Vuex

vue.js 애플리케이션에 대한 상태관리패턴 + 라이브러리다. 애플리케이션 모든 컴포넌트들의 중앙집중식저장소 역할로 데이터를 관리한다. 이 방식은 예측 가능한 방식으로 상태를 관리할 수 있다. 

기존의 단방향 통신은 데이터의 흐름이 직관적이라는 장점이 있지만, 부모 자식 단계가 많이 복잡해진다면 데이터의 전달하는 부분도 매우 복잡해져서 유지보수가 힘들다는 단점이 있다. 애플리케이션이 여러 구성 요소로 구성되고 더 커지는 경우 데이터를 공유하는 문제도 발생한다.

vuex는 데이터 관리하는데에는 효율적이지만, 소스가 복잡해 개념 이해와 시작에 비용이 든다. 단기간, 장기간 생산성 간 기회비용이 있다는 것도 유의해야한다. 대규모 프로젝트에는 vuex가 효율적인 선택이다.

 

2. Vuex 핵심컨셉

1) State

-  vuex는 단일 상태 트리를 사용한다.

-  중앙에서 관리하는 모든 상태 정보를 State가 관리한다. data 속성의 역할을 한다.

-  여러 컴포넌트 내부에 있는 특정 state를 중앙에서 하나로 관리한다. vuex를 활용하면 컴포넌트에서 사용하는 state를 한 눈에 파악이 가능하다.

반드시 Mutations에 정의된 method에 의해서만 변경된다.

-  State가 변경되면 해당 state를 공유하는 모든 컴포넌트의 DOM은 자동으로 렌더링된다.

-  모든 Vuew 컴포넌트는 Vuex Store에서 state 정보를 가져와 사용한다.

-  각 컴포넌트는 dispatch()를 사용해 Actions 내부의 method를 호출한다.

 

2) Actions

-  비동기 작업의 결과를 적용하려고 할 때 사용한다.

-  컴포넌트에서 dispatch() method 에 의해 호출된다. 이 때, 첫번째 인자값으로 context가 넘어온다.

-  BackEnd API와 통신해 Data Fetching 등의 작업을 수행한다. -> 동기적 작업 뿐 아니라 비동기 작업을 포함한다.

-  context로 store.js 파일 내에 있는 모든 요소(속성, method)의 변경 및 호출이 가능하지만 state를 직접 변경하는 것은 권장하지 않는다.

-  비동기 로직의 처리가 종료되면 Mutations에 정의되어 있는 method를 commit method를 이용해 호출한다.

-  State는 반드시 Mutations가 가진 method를 통해서만 조작하도록 하는데, 서비스 규모가 커지더라도 State 관리를 올바르게 하기 위한 것이다.

 

3) Mutations

-  Actions에서 commit() method에 의해 호출된다. 첫번재 인자값으로 state가 넘어온다.

Actions에서는 비동기적 작업을, Mutations에서는 동기적 작업만을 한다. Mutations에서 비동기적 작업이 있을 경우 state의 변화 시점이 명확하지 않을 수 있기 때문이다.

 

4) Getters

-  computed와 유사하다.

-  State를 변경하지 않고 활용해 계산을 수행한다. (data 가공)

Getters가 State 자체를 변경하지는 않고 활용할 뿐이다.

-  컴포넌트가 vuex의 state를 직접 접근하는 코드가 중복된다면 소스가 복잡해지고 가공하는 data가 많아지게 된다. 이를 방지하기 위해 getters를 사용한다.

 

5) 순서

1.  Vue Component : DOM. data 변경 event를 발생시킨다. dispatch method로 actions를 호출한다.

2.  Actions : axios를 활용해 BackEnd와 비동기통신을 한다. context.commit()으로 Mutations의 methods 중 메소드 하나를 호출한다.

3.  Mutations : 2에서 호출된 메소드의 첫번째 인자값으로 state를 받은 뒤 state를 변경한다.

4.  Vue Component : state의 data가 변경된 후 렌더링된다.

4-1.  State가 변경되면 Getter로 state를 가공해 계산한다.

4-2.  가공된 데이터를 Vue Component에서 사용해 렌더링한다.

 

3. vuex 설정

1.  main.js에서 store에 있는 파일을 import하고 vue instance에 설정한다.

2.  store/index.js에서 Vue.use()를 통해 Vuex를 설정한다. 이 파일에서 state, actions, getters, mutations를 포함하는 Vuex.Store을 만든다.

 

4. vuex 사용

state this.$store.state.data_name 방식으로 접근한다.
mapState import {mapState} from 'vuex'한다.
computed에서 ...mapState([사용할 state이름들])을 이용한다.
이렇게 하면 state이름으로 바로 접근할 수 있다.
getters this.$store.getters.getter_name 방식으로 사용한다.
mapGetters 사용하려는 파일에서 import {mapGetters} from 'vuex'; 한 뒤
computed에서 spreadSyntax를 사용해 값을 전부 가져온다. 
...mapGetters([사용할 getter 이름들])을 이용한다.
이렇게 하면 
{{getter이름}}처럼  getter이름으로 바로 접근할 수 있다.
mutations 직접 호출이 불가능하고 this.$store.commit('정의된 이름')으로 호출한다.
이 때 인자값으로 객체도 보낼 수 있다.
actions에서 호출할 때는 
context.commit('정의된 이름') 방식으로 호출한다. 
actions와 구분하기 위해 보통 대문자로 이름을 설정한다.
mapMutations import {mapMutaions} from 'vuex'한 뒤 
methods에서 ...mapMutations([사용할 mutations 이름들])을 이용한다.
이렇게 하면 
this.mutation이름 으로 메소드처럼 사용할 수 있다.
actions this.$store.dispath('정의된 이름')를 사용한다.
mapActions import {mapActions} from 'vuex'한다. 
methods에서 ...mapActions([사용할 actions이름들])을 이용해서 
this.action이름으로 메소드처럼 사용할 수 있다.
//예시
import { mapMutations, mapActions } from "vuex";
export default {
  name: "SubjectComponent",
  props: ["title"],
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    ...mapMutations({
      addMOne: "ADD_ONE",
      addMTenCount: "ADD_TEN_COUNT",
      addMObjCount: "ADD_OBJ_COUNT",
    }),
    ...mapActions(["asyncAddOne"]),
    addCount: function () {
      this.count += 1;
      // this.$store.commit('addOne');
      this.addMOne();
    },
    addTenCount: function () {
      this.count += 10;
      // this.$store.commit('addCount', 10);
      this.addMTenCount(10);
    },
    addObjCount: function () {
      let num = Math.round(Math.random() * 100);
      this.count += num;
      // this.$store.commit('addObjCount', { num });
      this.addMObjCount({ num });
    },
    asyncCount() {
      this.asyncAddOne();
    },
  },
};

댓글