원래는 이 블로그 용도를 개발 공부하면서 기록할 겸, 알고 있는 내용도 잊지 않게 기록의 용도로 사용하자 라고 생각을 했었는데, 조회수가 1이 생기는 것을 보고 다른 사람도 볼 수 있는데 반말을 쓰는 건 조금 아닌 것 같아 앞으로는 이 부분은 지양하면서 기록을 해보려고 합니다.
최근에는 Dart와 Flutter 공부를 집중적으로 하는 중이라 Nuxt는 알고 있거나 알아야 할 내용들에 조금 소홀하고 있긴 하지만 Nuxt는 몸으로 겪어본 만큼 계속 포스팅을 해야겠다 라는 생각이 드네요.
Nuxt에서 Vuex를 사용하는 방법에 대해 작성하려고 합니다.
아마 Vue를 경험하신 분이면 크게 어려운 점은 없을거라 생각이 듭니다.
Store
이 store 디렉토리에는 Vuex Store 파일들을 포함합니다.
또한
This directory cannot be renamed without extra configuration.
라고 디렉토리명 바꾸지 말라고 Nuxt 공식 홈페이지에 나와있으니 주의하도록 해야합니다.
Nuxt 프로젝트를 처음 생성하게 된다면 기본적으로 store 디렉토리가 생성되어 있을 것입니다.
Nuxt 공식 홈페이지에서는
Using a store to manage the state is important for every big application. That's why Nuxt.js implements Vuex in its core.
라고 대형 어플리케이션에서 이 store 를 사용하여 상태관리 하는 것이 굉장히 중요하며, Nuxt 또한 이러한 이유 때문에 Vuex 를 핵심기능으로 보고있습니다.
Store 활성화
Nuxt 기본 설정이 비활성화로 되어 있기 때문에 활성화를 시켜줘야 합니다.
store 디렉토리에 index.js 파일을 생성하게 되면 자동적으로 Store 기능이 활성화 됩니다.
Classic mode, Module mode
Nuxt.js 는 클래식 모드의 Store기능과 모듈 모드 두가지를 이용할 수 있습니다.. 클래식 모드는 Vuex.Store 객체를 인스턴스로 만들어 Store 기능을 사용하는 것이고 모듈 기능은 사용처에 맞게 모듈별로 저장소를 따로 만들어 관리하는 기능입니다.
Classic mode
store/index.js
import Vuex from 'vuex';
const store = () => new Vuex.Store({
})
export default store
이렇게 Vuex.Store의 인스턴스를 export 해주는 것만으로도 Store 기능을 사용할 수 있게 됩니다.
여기에 state나 mutations, actions, getters들을 넣어주면 Vuex 기능을 사용할 수 있게 됩니다.
p.s : Nuxt 3 버전에서부터는 Vuex 의 클래식모드를 지원하지 않는다고 하니 참고용으로만 알아두면 좋을 것 같습니다.
Module mode
store/index.js
export const state = () => ({
counter: 0
});
export const mutations = {
increment (state) {
state.counter++;
}
}
이렇게 각각의 속성들(state, mutations, getters, actions)을 위와 같이 export 해주면 Nuxt.js 는 알아서 모듈모드로 동작합니다.
클래식 모드 처럼 Vuex.Store의 인스턴스를 export 해주지 않아도 괜찮습니다.
그리고 Nuxt.js에서의 모듈 모드는 파일명으로 모듈 이름이 결정됩니다. 예를 들어서 todo.js 라는 이름으로 모듈을 하나 새로 만듭니다.
store/todo.js
export const state = () => ({
list: []
})
export const mutations = {
add(state, text) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}
위 todo.js 를 사용한 예제
pages/todo.vue
<template>
<ul>
<li v-for="todo in todos" :key="todo.text">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
</ul>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos () {
return this.$store.state.todos.list
}
},
methods: {
addTodo (e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todos/toggle'
})
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
p.s : Nuxt 라이프 사이클을 이용하여 actions 에서 The nuxtServerInit 를 사용할 수 있습니다.
nuxtServerInit 가 actions 에 정의되어 있고, universal mode 일 때 Nuxt 는 context 를 사용하여 이를 호출합니다. 서버측에서만 사용하기 때문에 클라이언트측에 직접 제공하려는 서버 데이터가 있을 때 유용하다고 합니다.
※ nuxt generate 를 실행하면 생성 된 모든 동적 경로에 대해 nuxtServerInit 가 실행됩니다.
store/index.js
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
또한 아래와 같이 사용도 가능합니다.
다만, 비동기 nuxtServerInit 작업은 Promise를 반환하거나 async / await를 활용하여 nuxt 서버가 대기 할 수 있도록 해야 합니다.
store/index.js
actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
추가적으로
Vuex 사용 시 store 에 저장된 값이 사용자의 F5 등 페이지 새로고침이 발생하는 경우, state 의 값이 모두 날아가는 현상에 대하여 궁금해서 조금 조사를 해보았습니다.
Vuex 자체가 JavaScript 레벨에서 데이터를 취급하기 때문에 새로고침 시 데이터가 모두 사라지게 됩니다.
React 의 Redux 라이브러리는 어떠한지 알아봤는데 Redux 도 똑같다고 하더군요.
다만, 이런 현상들을 보완하기 위해 Redux 에서는 Redux-persist , Vue 에서는 Vuex-persistantstate, Vuex-persist 등의 라이브러리가 존재합니다.
이러한 라이브러리들은 localstorage, session-storage, cookie 등을 활용하여 Vuex 의 데이터를 따로 해당 storage 나 cookie 등에 저장해두고 새로고침 시 storage 나 cookie 에 데이터가 있다면 다시 가져오는 방식으로 진행된다고 합니다.
앞으로 Nuxt에 대해서 계속 작성할 예정이고 프로젝트를 진행하면서 겪었던 경험들을 작성해볼 예정입니다.
'FE > Nuxt.js' 카테고리의 다른 글
Nuxt.js Toast Ui Editor 적용 (1) | 2021.04.26 |
---|---|
Nuxt.js routing 알아보기 (0) | 2021.04.23 |
Nuxt.js asyncData vs Fetch (0) | 2021.04.16 |
Nuxt.js 에서 Props 사용하기 (0) | 2021.04.15 |
Nuxt.js 란? (feat. SSR, CSR) (0) | 2021.04.09 |
댓글