Vuex in Nuxt

๋„‰์ŠคํŠธ์—์„œ ๋ทฐ์—‘์Šค(Vuex)๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ”„๋กœ์ ํŠธ ํด๋”์˜ ๋ฃจํŠธ ๋ ˆ๋ฒจ์— store ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ๋ฐ‘์— js ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

store folder

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Vuex ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ž„ํฌํŠธ ๋˜๋ฉด์„œ ๋ทฐ์—‘์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ํ”„๋กœ์ ํŠธ ํด๋”์— store ํด๋”๊ฐ€ ์—†๋‹ค๋ฉด ๋ทฐ์—‘์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ž๋™์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋น„ํ™œ์„ฑํ™”๋ž€ ๋นŒ๋“œ ํŒŒ์ผ์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋ทฐ์—‘์Šค ์‹œ์ž‘ํ•˜๊ธฐ

๋ทฐ์—‘์Šค๋Š” Vue.js์˜ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด์ž ํŒจํ„ด์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ทฐ์—‘์Šค๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅธ๋‹ค๋ฉด Vuex ์†Œ๊ฐœ ๊ธ€์„ ๋จผ์ € ํ•™์Šตํ•˜๊ณ  ์ดํ›„ ๋‚ด์šฉ์„ ํ•™์Šตํ•˜์„ธ์š”.

๋„‰์ŠคํŠธ์—์„œ ๋ทฐ์—‘์Šค๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” store/index.js ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์€ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// store/index.js
export const state = () => ({
  user: {}
})

export const mutations = {
  setUser(state, user) {
    state.user = user;
  }
}

export const actions = {
  async fetchUser(context) {
    const response = await axios.get('users/1');
    context.commit('setUser', response.data);
  }
}

๊ธฐ์กด ์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์œ„์™€ ๊ฐ™์ด ๊ธฐ๋ณธ ์ฝ”๋“œ๋งŒ ์ž‘์„ฑํ•ด ์ฃผ๋ฉด ๋„‰์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ทฐ์—‘์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ์™€ ์„ค์ • ์ž‘์—…์„ ์ง„ํ–‰ํ•ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ทฐ์—‘์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์ž‘์„ฑํ•˜๋˜ ์•„๋ž˜ ์„ค์ • ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

// ์•„๋ž˜ ์„ค์ • ์ฝ”๋“œ๋Š” Nuxt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด๋ถ€์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์„ค์ •ํ•ด ์คŒ
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

new Vuex.Store({
  // ...
})

์•ž์—์„œ ์•ˆ๋‚ดํ•œ store/index.js ํŒŒ์ผ์˜ ๋‚ด์šฉ์€ ๋ทฐ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๊ธฐ์กด์— ๋ทฐ์—‘์Šค๋ฅผ ์ ‘๊ทผํ•˜๋˜ ๋ฐฉ์‹๊ณผ ๋™์ผํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<template>
  <div>
    <p>{{ $store.state.user }}</p>
    <button @click="displayUser"></button>
  </div>
</template>

<script>
export default {
  methods: {
    displayUser() {
      const user = { name: '๋„‰์ŠคํŠธ' };
      this.$store.commit('setUser', user);
    }
  }
}
</script>

๋ทฐ์—‘์Šค์˜ ๋ชจ๋“ˆํ™”

store ํด๋” ๋ฐ‘์— ์ƒ์„ฑํ•œ index.js๋Š” ๋ทฐ์—‘์Šค์˜ ๋ชจ๋“ˆํ™” ๊ด€์ ์—์„œ ๋ฃจํŠธ ๋ชจ๋“ˆ์ด ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ index.js ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค๋ฅธ ์ด๋ฆ„์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ฉด ๋ทฐ์—‘์Šค์˜ ๋ชจ๋“ˆ์ด ๋ฉ๋‹ˆ๋‹ค. products.js ํŒŒ์ผ์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// store/products.js
export const state = () => ({
  items: []
})

export const mutations = {
  addItems(state, item) {
    state.items.push(item);
  }
}

์œ„ ์ฝ”๋“œ๋Š” ๋งˆ์น˜ ์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.












ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 


// Vue CLI๋กœ ์ƒ์„ฑํ•œ ํ”„๋กœ์ ํŠธ์—์„œ Vuex๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

new Vuex.Store({
  state: () => ({
    user: {}
  }),
  // ...
  modules: {
    products: {
      namespaced: true,
      state: () => ({
        items: []
      }),
      mutations: {
        addItems(state, item) {
          state.items.push(item);
        }
      }
    }
  }  
})

nuxtServerInit

nuxtServerInit ์†์„ฑ์€ ๋„‰์ŠคํŠธ์˜ universal ๋ชจ๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์•ก์…˜ ์†์„ฑ์ž…๋‹ˆ๋‹ค.

// store/index.js
actions: {
  nuxtServerInit(context, { req }) {
    if (req.session.user) {
      context.commit('user', req.session.user)
    }
  }
}

์œ„ ์†์„ฑ์€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ์‹œ์ ์— ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ† ์–ด์— ๋ฏธ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์„ค์ •ํ•ด ๋†“๊ฑฐ๋‚˜ ์„œ๋ฒ„์—์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ, ์„œ๋ฒ„์—์„œ ์„ธ์…˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์ด๊ณ  ์„ธ์…˜์— ์—ฐ๊ฒฐ๋œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์Šคํ† ์–ด์— ์ €์žฅํ•ด์•ผ ํ•  ๋•Œ ์œ„์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์Šคํ† ์–ด์— ๋ฏธ๋ฆฌ ๋‹ด์•„๋†“์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

nuxtServerInit ์•ก์…˜ ์†์„ฑ์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์Šคํ† ์–ด์˜ ์ปจํ…์ŠคํŠธ ์ •๋ณด๋ฅผ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋„‰์ŠคํŠธ์˜ ์ปจํ…์ŠคํŠธ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.



ย 
ย 

ย 




// store/index.js
actions: {
  nuxtServerInit(storeContext, nuxtContext) {
    storeContext.commit('๋ฎคํ…Œ์ด์…˜ ํ•จ์ˆ˜๋ช…');
    if (process.server) {
      const { req, res, beforeNuxtRender } = nuxtContext;
    }
  }
}

์œ„ ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ nuxtContext๋Š” asyncData ๋ฉ”์„œ๋“œ์˜ context ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.