본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section15] 215. 변형(Mutation) 소개 - 데이터를 변경하는 더 나은 방법

예측 가능한 상태 관리에 관해 이야기를 했었다.

예측 가능한 flow는 데이터 flow를 명확하게 정의하고, 데이터를 업데이트하고 얻을 때 특정 방식을 따르게 하여 오류 발생을 줄여준다.

 

 

# state 직접 변경 - 이상적인 상황 x

지금 Vuex를 사용하는 방식도 괜찮지만, Vuex의 철학을 완전히 따르지는 않고 있다.

$store.state를 직접적으로 이용하여 컴포넌트의 내부에서 state를 변경하고있다.

엄밀히 말하면 이런 식으로도 동작은 하지만, 이상적인 상황은 아니다.

애플리케이션 어디에서도 state를 바꿀 수 있고, 이는 전적으로 우리에게 달려있다.

만약 추가하거나 state.counter + 10으로 설정하거나

오타로 1을 두번 입력하여 11을 추가하는 등, 오류가 발생할 수도 있다.

methods: {
  addOne() {
    this.$store.state.counter = this.$store.state.counter + 11;
  },
},

 

이건 상태 변화 메커니즘에 대한 명확한 정의가 없기 때문.

지금은 어디서나 state를 바꿀 수 있다.

Vuex를 다르게 사용해야 하는 이유이기도 하다.

 

 

# state 변경방법 - mutations

앱 전반에 걸친 중앙데이터 저장소인 상태 저장소가 있고, 컴포넌트 내부에서 이 저장소와 통신한다.

점선 화살표인 이유는, 통신은 해야하지만 직접적으로는 아니기 때문.

지금처럼 구현한 것은 이상적이지 않다.

대신, Vuex에는 내장된 개념인 변형(Mutations)이 있다.

Mutations는 명확하게 정의된 메서드로 상태를 업데이트하는 로직을 가지고 있다.

컴포넌트 내부에서 직접 상태를 바꾸는 대신에 변형(Mutations)을 트리거하게 된다.

변형을 트리거함으로써 상태를 변경하고자 하는 모든 컴포넌트는 같은 방식으로 동작하게 된다.

같은 방식으로 변경하는 것이 보장된다.

 

 

 

## mutations 활용 예시

컴포넌트인 ChangeCounter.vue를 추가해보자.

store.state.counter에 접근하여 1만큼 추가할 수 있다.

<!--ChangeCounter.vue-->
<template>
  <button @click="addOne">Add 1</button>
</template>
<script>
export default {
  methods: {
    addOne() {
      this.$store.state.counter++;
    },
  },
};
</script>

 

App.vue에 ChangeCounter를 불러온다.

총 버튼이 2개다. 하나는 App.vue 컴포넌트에, 하나는 ChangeCounter.vue에 있다.

둘다 1만큼 추가해야하지만, 오타로 인해 App.vue컴포넌트의 버튼은 11을 입력했다고 하자.

따라서 두 버튼 중, 하나는 클릭 시 11이 추가되고, 하나는 1이 추가된다.

앱의 다른 공간에서 상태를 업데이트하는 것을 보여주기위해.

<template>
  <base-container title="Vuex">
    <the-counter></the-counter>
    <button @click="addOne">Add 1</button>
    <change-counter></change-counter>
  </base-container>
</template>

<script>
import BaseContainer from './components/BaseContainer.vue';
import TheCounter from './components/TheCounter.vue';
import ChangeCounter from './components/ChangeCounter.vue';

export default {
  components: {
    BaseContainer,
    TheCounter,
    ChangeCounter,
  },
  methods: {
    addOne() {
      this.$store.state.counter = this.$store.state.counter + 11; //11씩 추가
    },
  },
};
</script>

 

만약 2를 추가하기로 한다면, 두 개의 컴포넌트(App.vue, ChangeCounter.vue)로 가서 각각 로직을 바꿔야한다.

더 큰 애플리케이션이라면, 로직을 수정해야할 장소가 더 많아진다.

그리고, 코드가 중복된다.

따라서 Mutation이라는 개념을 사용해야한다.

 

 

1. mutations 추가 방법

store을 만든 main.js에 state 외에도 mutations를 넣을 수 있다.

- mutations는 객체를 받고, 이 객체에 메서드를 정의한다.

- 이 메서드는 상태를 변경하는 로직이다.

- 이 메서드는 자동으로 현재상태를 인수로 받는다. 인수로 받도록 Vuex가 보장한다.

// main.js
mutations: {
  increment(state) {},
},

Vuex는 이 메서드가 트리거될 때 현재 상태를 준다.

메서드를 트리거하는 방식을 보자.

 

현재 상태가 여기 들어가기 때문에 최신 상태가 보장되고,

state.counter에 접근하여 1을 추가한다.

mutations: {
  increment(state) {
    state.counter++;
    // state.counter = state.counter + 1; 이것도 가능.
  },
},

 

만약 로직을 바꾸어야 한다면, mutations인 이곳에서 바꾸면 된다.

이제 상태를 바꿔야하는 모든 곳에서 mutation을 트리거한다.

애플리케이션에 필요한 만큼의 mutation을 넣을 수 있다.

 

 

 

2. mutations 트리거

예시에서의 mutation은 한 개이고, App.vue에 있는 button과 ChangeCounter.vue에 있는 button을 통해 mutation을 트리거하고싶다.

 

먼저 ChangeCounter.vue에 있는 버튼부터 해보자.

변형을 트리거하기위해 this.$store에 접근해보자.

commit 메서드가 있다. Vuex에 내장된 메서드로, store에 있다.

commit은 수행하고자 하는 mutation의 이름을 받는다.

이 경우, 'increment'이다. 이름은 문자열로 제공되어야 한다.

// ChangeCounter.vue
methods: {
  // 기존 방법
  // addOne() {
  //    this.$stoure.state.counter++;
  // },
  addOne() {
    this.$store.commit('increment');
  },
},

 

App.vue에서도 마찬가지로 commit을 추가하자.

 

 

이렇게 상태가 업데이트되는 로직을 컴포넌트 밖으로 옮겨 store의 mutations으로 옮겼다.

그리고 컴포넌트 내부에서 해당 mutation을 commit했다.

 

이렇게 저장하면 여전히 잘 작동한다.

mutation을 활용하여 좀 더 멋지고 예측 가능한 형태로 상태를 업데이트할 수 있게 되었다.

 

 

** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.