Vue에서 컴포넌트끼리 데이터를 주고 받는 방식이 궁금하다면?
2025.11.19 - [Web/Vue] - Vue.js SFC, props, emit으로 부모-자식 데이터 흐름 잡기
Vue.js SFC, props, emit으로 부모-자식 데이터 흐름 잡기
Vue가 뭔지, 그리고 Vue의 기본 문법이 궁금하시다면? 2025.11.18 - [Web/Vue] - Vue.js 입문 : 기본 철학과 기본 문법 정리 Vue.js 입문 : 기본 철학과 기본 문법 정리1. Vue.js는 어떤 프레임워크인가? Vue.js는
sproutinghye.tistory.com
1. 왜 Vuex가 필요할까?
간단한 프로젝트에서는 props와 $emit만으로도 데이터 흐름을 관리할 수 있습니다.
하지만 화면이 많아지고, 컴포넌트가 복잡해지면 이런 상황이 올 수 있습니다.
- A → B → C → D로 데이터가 계속 전달됨 (prop drilling)
- 여러 컴포넌트가 동일한 데이터를 써야 해서 어디서 바꿔야 할지 헷갈림
- 로그인 정보, 사용자 정보, 토큰, 공통 필터 값 등 "전역 상태"가 점점 늘어남
이럴 때를 위해 Vue에서는 공식 상태 관리 패턴 + 라이브러리로 Vuex를 제공합니다.
Vuex는 전역에서 공유하는 하나의 중앙 저장소(store)를 두고,
그 안에서 상태(state)를 예측 가능하게 관리하도록 도와주는 도구입니다.
"Vuex is a state management pattern + library for Vue.js applications."
- Vuex 공식 문서
쉽게 말하자면, Vuex는 컴포넌트 간 데이터 지옥에 빠지는 것을 방지합니다.
2. Vuex의 핵심 4요소
Vuex를 이해할 때 가장 중요한 키워드는 딱 4개입니다.
1) state - 전역에서 공유하는 실제 데이터
2) getters - state를 기반으로 한 계산된 값(전역 computed 느낌)
3) mutations - state를 동기적으로 변경하는 유일한 방법
4) actions - 비동기 로직, API 호출 등을 처리한 뒤 mutation을 호출하는 곳
Vuex 공식 문서에서도 이 네 가지를 기본 개념으로 설명하면서,
"state는 하나의 객체로 관리하고, mutations를 통해서만 변경하라"고 강조합니다.
이제 vuex를 설치하고, 이를 이용해 전역 상태를 관리하는 방법을 알아보겠습니다.
3. Vuex 설치 및 기본 스토어 생성
- 설치
Vue2와 Vuex3 기준으로는 아래 명령어를 사용하시면 됩니다.
npm install vuex@3
# 또는
yarn add vuex@3
- 기본 스토어 생성
설치가 되었다면 아래와 같이 기본 사용 설정을 해줍니다.
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
INCREMENT(state) {
state.count++
}
},
actions: {
increment({ commit }) {
commit('INCREMENT')
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
})
그 다음, 루트 인스턴스에 스토어를 주입합니다.
// main.js
import Vue form 'vue'
import App from './App.vue'
import store from './store'
new Vue({
store,
render: h => h(App)
}).$mount('#app')
이제 모든 하위 컴포넌트에서 this.$store로 Vuex에 접근할 수 있습니다.
4. state
state는 Vuex 스토어 안에서 관리되는 전역 데이터입니다.
state는 아래와 같이 선언할 수 있습니다.
export default new Vuex.Store({
state: {
count: 0,
todos: [
{id: 1, text: 'Vue 공부하기', done: false},
{id: 2, text: '운동하기', done: true}
]
}
})
컴포넌트에서는 state를 두 가지 방식으로 가져다 쓸 수 있습니다.
첫 번째, this.$store.state.count 형태로 직접 참조
두 번째, mapState 헬퍼를 사용해 computed에 매핑
[ this.$store.state 사용 ]
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
[ mapState 헬퍼 사용 ]
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count', 'todos'])
}
}
이렇게 mapState를 사용하면 템플릿에서 그냥 {{ count }}, {{ todos }}처럼 사용할 수 있습니다.
5. getters
getters는 state를 기반으로 계산된 값을 반환합니다.
전역에서 쓰는 computed 같은 친구라고 볼 수 있어요.
예를 들어 완료된 투두만 필터링 하고 싶다면, 아래처럼 store를 작성할 수 있습니다.
// store/index.js
getters: {
doneTodos(state) {
return state.todos.filter(todo => todo.done)
},
doneTodosCount(state, getters) {
return getters.doneTodos.length
}
}
컴포넌트에서는 getters를 두 가지 방식으로 가져다 쓸 수 있습니다.
첫 번째, this.$store.getters.doneTodos 형태로 직접 참조
두 번째, mapGetters 헬퍼를 사용
[ this.$store.getters ]
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
[ mapGetters ]
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['doneTodos', 'doneTodosCount'])
}
}
이와 같이 Vuex 공식 문서에서는 getters를
"전역 스토어에서 사용하는 computed properties와 같은 역할"이라고 설명합니다.
6. mutations
mutations는 state를 바꿀 수 있는 유일한 방법입니다.
Vuex의 중요한 규칙은 state를 직접 바꾸지 말고, 반드시 mutation을 통해서 변경하는 것입니다.
mutations는 아래와 같이 선언할 수 있습니다.
// store/index.js
mutations: {
INCREMENT(state) {
state.count++
},
ADD_TODO(state, payload) {
state.todos.push({
id: Date.now(),
text: payload.text,
done: false
})
},
TOGGLE_TODO(state, id) {
const target = state.todos.find(t => t.id == id)
if (target) target.done = !target.done
}
}
컴포넌트에서 mutation을 호출하는 방법은 두 가지가 있습니다.
첫 번째, this.$store.commit 형태로 직접 호출
두 번째, mapMutations 헬퍼 사용
[ this.$store.commit ]
this.$store.commit('INCREMENT')
this.$store.commit('ADD_TODO', {text: '새 할 일 추가'})
this.$store.commit('TOGGLE_TODO', todoId)
[ mapMutations 헬퍼 사용 ]
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations(['INCREMENT', 'ADD_TODO', 'TOGGLE_TODO'])
}
}
Vuex 공식 문서에서도 mutations는 반드시 동기(synchronous)로 작성하라고 명시되어 있습니다.
이유는 DevTools 타임라인에서 상태 변경을 예측 가능하게 추적하기 위함입니다.
7. actions
actions는 보통 다음 역할을 맡습니다.
- API 호출 (Axios 등)
- setTimeout, 비동기 처리
- 여러 mutation을 한 번에 조합해서 실행
actions는 아래와 같이 선언할 수 있습니다.
// store/index.js
import axios from 'axios'
export default new Vuex.Store({
// state, mutations ...
actions: {
async fetchTodos({ commit }) {
const res = await axios.get(
'https://jsonplaceholder.typicode.com/todos?_limit=5'
)
commit('SET_TODOS', res.data)
}
},
mutations: {
SET_TODOS(state, todos) {
state.todos = todos
}
}
})
컴포넌트에서 action을 호출하는 방법은 두 가지가 있습니다.
첫 번째, this.$store.dispatch('fetchTodos') 형태로 직접 호출
두 번째, mapActions 헬퍼 사용
[ this.$store.dispatch 사용 ]
export default {
created() {
this.$store.dispatch('fetchTodos')
}
}
[ mapActions 사용 ]
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions(['fetchTodos']) // this.fetchTodos()를 this.$store.dispatch('fetchTodos')에 매핑
}
}
Vuex 공식 문서에서 actions는
"비동기 작업을 처리한 뒤, 그 결과를 mutation으로 전달하는 역할"로 설명합니다.
정리
- Vuex는 Vue 공식 상태 관리 패턴 + 라이브러리
- 핵심요소 4개
- state: 전역 데이터
- getters: state 기반 계산 값 (전역 computed)
- mutations: state 변경, 반드시 동기적
- actions: 비동기 로직, mutation 호출 담당
- 헬퍼 함수
- mapState, mapGetters, mapMutations, mapActions
출처
프로젝트가 커지면 하나의 store에 모든 state/mutation/action을 몰아넣기 어렵습니다.
그래서 사용하는 것이 modules(모듈) 기능입니다.
state, getters, mutations, actions와 modules를 활용한 예제는 다음 글에서 다뤄보겠습니다.
'Framework > Vue' 카테고리의 다른 글
| Vuex 모듈(modules)로 스토어 깔끔하게 나누기 (0) | 2025.11.21 |
|---|---|
| Vuex를 이용한 Vue 전역 상태 관리 예제 (0) | 2025.11.20 |
| Vue Router와 Axios 활용해 라우팅 + API 연동으로 SPA 만들기 (0) | 2025.11.20 |
| Vue Router 기초 (Vue 2 + Vue Router 3) (1) | 2025.11.19 |
| Vue.js SFC, props, emit으로 부모-자식 데이터 흐름 잡기 (0) | 2025.11.19 |