반응형

Vuex는 Vue.js 애플리케이션에서 상태 관리를 중앙 집중화할 수 있도록 도와주는 공식적인 상태 관리 패턴 및 라이브러리입니다.

Vuex를 사용하면 애플리케이션의 상태를 중앙에서 관리하고, 이를 다양한 컴포넌트들이 공유할 수 있습니다.

Vuex는 특히 규모가 큰 애플리케이션에서 컴포넌트 간의 상태 관리를 단순화하고, 일관된 상태 관리를 가능하게 합니다.

 

Vuex의 주요 개념

 

1. State (상태)

state는 애플리케이션의 중앙에서 관리되는 상태를 정의합니다. Vue 컴포넌트의 data와 유사하지만, 여러 컴포넌트가 공유할 수 있는 중앙 집중식 상태입니다.

const store = createStore({
  state: {
    todos: []
  },
});

2. Mutations (변이)

mutations는 상태를 변경하는 메서드입니다. 상태를 변경할 때는 반드시 mutations를 통해 변경해야 합니다. 이는 Vuex의 핵심 개념 중 하나로, 상태 변이를 추적하고 디버깅을 쉽게 만들어줍니다.

mutations: {
  setTodos(state, todos) {
    state.todos = todos;
  },
  addTodo(state, todo) {
    state.todos.push(todo);
  },
  removeTodo(state, index) {
    state.todos.splice(index, 1);
  },
  updateTodoStatus(state, { index, completed }) {
    state.todos[index].completed = completed;
  }
}

3. Actions (액션)

actionsmutations와 유사하지만, 비동기 작업을 처리할 수 있습니다. 액션은 mutations를 커밋하여 상태를 변경합니다. 예를 들어, API 호출 후 응답 데이터를 상태에 반영하는 작업을 actions에서 처리합니다.

 

actions: {
  loadTodos({ commit }) {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      commit('setTodos', JSON.parse(savedTodos));
    }
  },
  saveTodos({ state }) {
    localStorage.setItem('todos', JSON.stringify(state.todos));
  },
  addTodo({ commit, dispatch }, todoText) {
    const newTodo = { text: todoText, completed: false };
    commit('addTodo', newTodo);
    dispatch('saveTodos');
  },
  removeTodo({ commit, dispatch }, index) {
    commit('removeTodo', index);
    dispatch('saveTodos');
  },
  toggleTodoStatus({ commit, dispatch }, payload) {
    commit('updateTodoStatus', payload);
    dispatch('saveTodos');
  }
}

 

4. Getters (게터)

getters는 상태에서 값을 가져올 때 사용됩니다. Vue 컴포넌트에서 computed 속성과 유사하게 동작합니다. 상태를 가공하거나 필터링하여 반환할 수 있습니다.

getters: {
  todos(state) {
    return state.todos;
  }
}

5. Store (스토어)

Vuex store는 Vuex의 중심입니다. 상태(state), 변이(mutations), 액션(actions), 게터(getters) 등을 포함하여 애플리케이션의 전체 상태를 관리합니다. 컴포넌트는 이 스토어를 통해 중앙 상태에 접근하고, 변경할 수 있습니다.

import { createStore } from 'vuex';

const store = createStore({
  state: {
    todos: []
  },
  mutations: { /* 변이들 */ },
  actions: { /* 액션들 */ },
  getters: { /* 게터들 */ }
});

export default store;

 

 

 

 

 

 

Vuex의 사용 예시

 

다음은 Vuex를 활용하여 To-Do 리스트 애플리케이션의 상태를 관리하는 방법에 대한 예시입니다.

 

1. 상태 정의 및 초기화

todos 배열을 상태로 정의하고, 로컬 스토리지에서 저장된 할 일 목록을 불러와 todos에 저장합니다.

state: {
  todos: []
}

2. 상태 업데이트

사용자가 새로운 할 일을 추가하거나, 할 일의 상태를 변경하면 Vuex의 mutations를 통해 상태가 업데이트됩니다.

mutations: {
  addTodo(state, todo) {
    state.todos.push(todo);
  },
  updateTodoStatus(state, { index, completed }) {
    state.todos[index].completed = completed;
  }
}

3. 액션을 통한 상태 관리

actions를 통해 비동기 작업과 상태 변이를 처리합니다. 예를 들어, 로컬 스토리지에 할 일 목록을 저장하는 작업은 actions에서 처리됩니다.

actions: {
  saveTodos({ state }) {
    localStorage.setItem('todos', JSON.stringify(state.todos));
  }
}

4. 컴포넌트에서 Vuex 상태 접근

컴포넌트에서는 mapGetters, mapActions를 사용하여 Vuex 상태와 메서드를 간단히 연결할 수 있습니다.

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
  computed: {
    ...mapGetters(['todos'])
  },
  methods: {
    ...mapActions(['addTodo', 'toggleTodoStatus', 'removeTodo'])
  }
}
</script>

요약

 

중앙 집중화된 상태 관리: Vuex를 사용하면 상태를 중앙에서 관리하여 컴포넌트 간의 상태 공유와 변경을 쉽게 추적할 수 있습니다.

예측 가능한 상태 관리: 모든 상태 변경은 mutations를 통해 이루어지므로, 상태 변경을 쉽게 예측하고 디버깅할 수 있습니다.

비동기 작업 관리: 비동기 작업은 actions를 통해 관리되어, 복잡한 비동기 로직도 쉽게 처리할 수 있습니다.

Vue 컴포넌트와의 통합: mapGettersmapActions를 통해 Vue 컴포넌트와 Vuex 상태 및 메서드를 간단히 연결할 수 있습니다.

 

Vuex는 규모가 큰 애플리케이션에서 특히 유용하며, 상태를 일관되게 유지하고 컴포넌트 간의 상태 관리 복잡성을 줄여줍니다.

반응형
반응형

Vuex를 사용하여 To-Do 리스트 애플리케이션을 리팩토링하는 방법을 설명하겠습니다.

Vuex는 Vue.js 애플리케이션에서 상태 관리를 중앙에서 처리할 수 있도록 도와주는 라이브러리입니다.

이 예제에서는 Vuex를 사용하여 할 일 목록(todos)을 중앙에서 관리하고, 컴포넌트들이 Vuex 스토어를 통해 상태를 접근하고 수정하도록 하겠습니다.

 

1. Vuex 설치

 

먼저 Vuex를 설치해야 합니다.

npm install vuex@next

2. Vuex 스토어 설정 (store/index.js)

 

src/store/index.js 파일을 생성하고, Vuex 스토어를 설정합니다.

import { createStore } from 'vuex'

const store = createStore({
  state: {
    todos: []
  },
  mutations: {
    setTodos(state, todos) {
      state.todos = todos;
    },
    addTodo(state, todo) {
      state.todos.push(todo);
    },
    removeTodo(state, index) {
      if (index >= 0 && index < state.todos.length) {
        state.todos.splice(index, 1);
      }
    },
    updateTodoStatus(state, { index, completed }) {
      if (index >= 0 && index < state.todos.length) {
        state.todos[index].completed = completed;
      }
    }
  },
  actions: {
    loadTodos({ commit }) {
      const savedTodos = localStorage.getItem('todos');
      if (savedTodos) {
        commit('setTodos', JSON.parse(savedTodos));
      }
    },
    saveTodos({ state }) {
      localStorage.setItem('todos', JSON.stringify(state.todos));
    },
    addTodo({ commit, dispatch }, todoText) {
      const newTodo = { text: todoText, completed: false };
      commit('addTodo', newTodo);
      dispatch('saveTodos');
    },
    removeTodo({ commit, dispatch }, index) {
      commit('removeTodo', index);
      dispatch('saveTodos');
    },
    toggleTodoStatus({ commit, dispatch }, payload) {
      const { index, completed } = payload;
      console.log('toggleTodoStatus', index, completed);
      commit('updateTodoStatus', { index, completed });
      dispatch('saveTodos');
    }
  },
  getters: {
    todos(state) {
      return state.todos;
    }
  }
});

export default store;

3. Vue 애플리케이션에 Vuex 추가 (main.js)

 

main.js 파일에서 Vuex 스토어를 Vue 애플리케이션에 추가합니다.

import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { loadFonts } from './plugins/webfontloader'
import router from './router'  // Vue Router를 추가
import store from './store'  // Vuex 스토어를 가져옵니다.


loadFonts()

createApp(App)
  .use(vuetify)
  .use(router)  // Vue Router 사용
  .use(store)  // Vuex 스토어를 사용합니다.
  .mount('#app')

4. ToDoList.vue 컴포넌트 수정

 

이제 ToDoList.vue 컴포넌트를 수정하여 Vuex 스토어에서 상태를 가져오고, 할 일을 추가 및 삭제하는 기능을 구현합니다.

<template>
  <v-container>
    <v-row>
      <v-col>
        <h1>Vue.js To-Do App</h1>
        <AddTodo @add-todo="addTodo" />
        <v-list>
          <v-list-item
            v-for="(todo, index) in todos"
            :key="index"
            @click="$router.push({ name: 'ToDoDetail', params: { id: index } })"
          >
            <template v-slot:prepend>
              <v-checkbox
                v-model="todo.completed"
                @click.stop="toggleTodoStatus({ index, completed: !todo.completed })"
                hide-details
              />
            </template>
            
            <v-list-item-title>{{ todo.text }}</v-list-item-title>
            
            <template v-slot:append>
              <v-btn icon="mdi-delete" size="small" @click.stop="removeTodo(index)">
              </v-btn>
            </template>
          </v-list-item>
        </v-list>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import AddTodo from './AddTodo.vue'
import { mapActions, mapGetters } from 'vuex'

export default {
  name: 'ToDoList',
  components: { AddTodo },
  computed: {
    ...mapGetters(['todos'])  // Vuex에서 todos 상태를 가져옵니다.
  },
  methods: {
    ...mapActions(['addTodo', 'removeTodo', 'toggleTodoStatus']),  // Vuex 액션들을 가져옵니다.
  },
  created() {
    this.$store.dispatch('loadTodos')  // Vuex 스토어에서 할 일을 로드합니다.
  }
}
</script>

5. TodoDetail.vue 컴포넌트 수정

 

TodoDetail.vue에서 Vuex 상태를 사용하도록 수정합니다.

<template>
    <v-container>
      <h2>To-Do Detail</h2>
      <v-card>
        <v-card-text>
          <p>ID: {{ id }}</p>
          <p v-if="todo">Text: {{ todo.text }}</p>
          <p v-else>Todo not found</p>
        </v-card-text>
      </v-card>
      <v-btn @click="$router.push('/')">Back</v-btn>
    </v-container>
  </template>
  
  <script>
  import { mapGetters } from 'vuex'
  
  export default {
    props: {
      id: {
        type: String,
        required: true
      }
    },
    computed: {
      ...mapGetters(['todos']),
      todo() {
        return this.todos[this.id]
      }
    }
  }
  </script>

 

1. Vuex 상태 관리:

state: todos 배열을 중앙에서 관리합니다.

mutations: 상태를 직접적으로 변경하는 로직을 포함합니다(addTodo, removeTodo, updateTodoStatus).

actions: 비동기 작업이나 여러 변형을 처리하고, 상태를 변경하는 메서드를 포함합니다(loadTodos, saveTodos 등).

2. ToDoList.vue 컴포넌트:

computed: mapGetters를 통해 Vuex에서 todos 상태를 가져옵니다.

methods: mapActions를 통해 Vuex 액션을 사용하여 할 일을 추가, 삭제, 상태를 변경하고, 로컬 스토리지와 동기화합니다.

created: 컴포넌트가 생성될 때 loadTodos 액션을 호출하여 로컬 스토리지에서 저장된 할 일 목록을 불러옵니다.


이전 블로그

vue to-do 리스트 구현 5 - router 구현

https://juntcom.tistory.com/321 

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

Vuetify 문서 레퍼런스 가이드  (0) 2024.08.17
vue vuex 란  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17
vue to-do 리스트 구현 5 - router 구현  (0) 2024.08.17
vue to-do 리스트 구현 4 - vuetify 적용  (0) 2024.08.16

+ Recent posts