HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
💌
JJong’s Archive
/
🏞️
Vue
/
Vuex(Store)

Vuex(Store)

Select
Nov 29, 2023
아무런 관계 없는 두 컴포넌트간에 데이터를 주고받으려면?
⇒ store로 데이터와 메소드를 관리한다
 

1. JS로 상태관리 구현

  • 동일한 객체를 data메소드의 리턴 값으로 쓰면, 해당 객체를 쓰는 컴포넌트의 data는 동기화된다(반응형)
    • 즉, 한 컴포넌트에서 객체 데이터를 변경하면, 다른 컴포넌트의 객체 데이터도 같이 변경된다
    • ⇒ data는 proxy로 관리되기 때문!
      export const store = { msg: '', count: 0 }
      index.js
      <template> <h1 @click="increaseCount">{{ count }}</h1> </template> import { store } from '~/store' .. data() { return store //msg, count 데이터를 가짐 }, methods: { increaseCount() { this.count += 1 //두 컴포넌트중 하나라도 이 메소드로 데이터를 변경하면 다른 한 컴포넌트의 데이터도 같이 변경 } }
      Hello.vue, World.vue
  • data 메소드 외부에서도 반응형이 되려면, vue의 reactive 메소드 안에 객체를 넣어서 값으로 주입해주면 된다
    • import {reactive} from 'vue' export const store = reactive({ msg: '', count: 0 }) export const mutations = { increaseCount() { store.count += 1 //store가 reactive 없이 그냥 객체였다면, //이 메소드로는 컴포넌트들끼리 동기화 불가 } }
      index.js
  • 이렇게 state, getters, mutations, actions로 기능을 분리해서 상태관리를 직접 만들 수 있다
    • state : 상태 데이터들
      • 컴포넌트의 data()에서 사용
    • getters : 상태 데이터를 이용해서 만든 새로운 데이터들
      • 컴포넌트의 computed에서 사용
    • mutations : 상태 데이터를 조작하는 메소드들
    • actions : 상태와 관련 없는 메소드들, 비동기(ex. api 통신)
    •  
       
       

2. Vuex로 상태관리

[설치]
npm install vuex
 
[store 생성]
  1. vuex의 createStore메소드에 state, getters, mutations, actions를 모은 객체 주입
      • mutations, getters의 메소드들은 매개변수로 state를 받을 수 있다. 이를 이용해 state에 접근가능
      • actions의 메소드에서는 매개변수로 context 객체를 받을 수 있다
        • context 안에는 state, getters, commit(뮤테이션), dispatch(액션)가 있다
      • 당연히 매개변수들의 이름은 아무거나 ㄱㅊ
      import { createStore } from "vuex"; export default createStore({ state() { return { msg: 'hello', count: 0 } }, getters: { reverseMsg(state) { return state.msg.split('').reverse().join('') } }, mutations: { increaseCount(state) { state.count+=1 }, insertTodoText(state, newVal) { state.msg = newVal } }, actions: { async fetchTodo(context, payload) { //payload는 그냥 데이터 매개변수.. const todo = await fetch('https://jsonplaceholder.typicode.com/todos/1') .then(res => res.json()) context.commit('insertTodoText', todo.title) } } })
      store/index.js
  1. 2를 app 플러그인으로 넣어줌(app.use(store))
    1. .. import store from './store' const app = createApp(App) app.use(store) app.mount('#app')
      main.js
 
[store 사용]
  1. 전역에서 state 접근 : this.$store.state.상태
  1. 전역에서 getters 접근 : this.$store.getters.게터
  1. 전역에서 뮤테이션 메소드 실행 : this.$store.commit(’뮤테이션이름’)
  1. 전역에서 액션 메소드 실행 : this.$store.dispatch(’액션이름’)
  • state, getters 데이터 모두 data메소드가 아닌 computed에 등록해야함에 주의!!
  • 뮤테이션과 액션은 methods에서 호출
 
ex) App에서 버튼으로 액션과 뮤테이션을 실행하여 state를 변경하면, 같은 store를 쓰는 Hello의 데이터까지 반영된다
<template> <h1>{{ msg }}</h1> <button @click="$store.dispatch('fetchTodo')"> changeMsg </button> <h2>{{ count }}</h2> <button @click="$store.commit('increaseCount')"> +1 </button> <Hello /> </template> <script> import Hello from '~/components/Hello/Hello' export default { components: { Hello }, computed: { msg() { //state 데이터 return this.$store.state.msg }, count() { //state 데이터 return this.$store.state.count } }, } </script>
App.vue
<template> <h1>{{ reverseMsg }} / {{ count }}</h1> </template> <script> export default { computed: { count() { //state 데이터 return this.$store.state.count }, reverseMsg() { //getters 데이터 return this.$store.getters.reverseMsg } } } </script> <style scoped lang="scss"> h1 { color: pink } </style>
Hello.vue
 
 

store를 모듈로 관리하기

[생성]
  1. 분리하고 싶은만큼 js파일을 만들어서, 일반 js 객체를 export
      • 이전에 createStore 안에 주입했던 객체와 똑같다
      • namespaced: true 옵션을 추가한다
      export default { namespaced: true, state() { .. }, ..
  1. 최상위 store로 index.js에서 createStore를 해서, modules 옵션을 추가한 후 앞서 만든 js객체들을 등록
    1. import 스토어모듈1 from '..' import 스토어모듈2 from '..' export default createStore({ .. modules: { 스토어모듈1, 스토어모듈2 } })
 
[사용]
방법1) ⇒ 기존처럼 객체 값으로
  1. state는 this.$store.state.모듈이름.state이름
  1. getters는 this.$store.getters[’모듈이름/게터이름’]
  1. mutations은 this.$store.commit(’모듈이름/뮤테이션이름’)으로 실행
 
방법2) ⇒ vuex의 map 사용
import { mapState, mapGetters, mapMutations, mapActions } from ‘vuex’ export default { computed: { ...mapState('모듈이름', [ '상태이름1', '상태이름2' ,, ]), ...mapGetters('모듈이름', [ '게터이름1', '게터이름2' ,, ]) }, methods: { ...mapMutations('모듈이름', [ '뮤테이션이름1', '뮤테이션이름2' ,, ]), ...mapActions('모듈이름', [ '액션이름1', '액션이름2' ,, ]) } }
  • 최상위 store에 등록된 것은 …mapState([’상태이름’]) 처럼 모듈 이름 없이 배열에 이름으로 바로 등록할 수 있다
    • export default { computed: { …mapState([’상태이름’]), .. }