똑같은 삽질은 2번 하지 말자

Composition API를 쓸 때 Vuex는? 본문

카테고리 없음

Composition API를 쓸 때 Vuex는?

곽빵 2022. 3. 5. 16:39

개요

Options API에서 Composition API에 마이그레이션 하는중.. vuex는 어떻게 써야할까?

를 고민하는중에 배웠거나 느꼈던 점들에 대해 적어보고자 한다.

헷갈렸던 개념

내가 지금 바꾸려는 환경은 nuxt가 아니고 그냥 vue를 쓰고 있는 곳이다.

아주 기본이지만 nuxt에서는 store 라는 디렉터리 안에 js나 ts파일을 생성하는 순간

.nuxt 빌드 결과물 안에 store.js 가 생성되어 있는걸 확인할 수 있다.

(store.js에는 우리가 Vue에서 Vuex를 쓰기위해 쓰던 코드들이 들어있다.)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// ..이하 생략

 

즉, 이렇게 파일을 만드는것만 으로도 store 인스턴스(this.$store)에 접근할 수 있게된다.

처음에 이런 store 인스턴스가 어디에서 생성되서 어디에서 Vue 인스턴스에 주입이 되는지 까먹어버려서 좀 헤맸다 잘 기억해두자

 

Composition API를 쓰면서 어떻게 Vuex를 type-safe하게  쓸 수 있을까?

vuex-module-decorators

https://typescript.nuxtjs.org/cookbook/store/

 

Nuxt TypeScript

TypeScript Support for Nuxt.js

typescript.nuxtjs.org

 

vuex-module-decorators를 선택한 이유?

  • setup function안에서는 this를 쓸 수 없다.(context.root를 쓸 수 있지만 deprecated 되므로 vue3이 되면 쓸 수 없음으로 배제)
  • @nuxtjs/composition-api 에 있는 useStore를 쓰면 type을 보장시키기가 어렵다..(vue.d.ts를 이용하면 방법이 있겠지믄,,ㅠ)
  • vuex-module-decorators는 store 내부에서 정의한 타입을 그대로 적용해서 가져올 수 있었다.

여기서 store 인스턴스의 주입이 어디서 일어나는지 까먹어서 헷갈렸던 부분인데 실제로 코드를 보면

store/store-accesor.ts

import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import Account from '@/store/account'

/* eslint-disable import/no-mutable-exports */
let accountStore: Account

const initialiseStores = (store: Store<Object>): void => {
  accountStore = getModule(Account, store)
}

export { initialiseStores, accountStore }

store/index.ts

import { Store } from 'vuex'
import { initialiseStores } from './store-accesor'

const initializer = (store: Store<Object>): void => initialiseStores(store)
export const plugins = [initializer]
export * from './store-accesor'

page1.vue

<script lang="ts">
import { defineComponent } from '@nuxtjs/composition-api'
import { accountStore } from '~/store/index'

export default defineComponent({
  mounted() {
    console.log(accountStore.todoList)
  },
})
</script>

store-accesor를 이용해 accountStore에 접근할 수 있게 해준다.

하지만, 처음에는 이러한 개념이 좀 헷갈렸다. 애초에 nuxt에서 store 인스턴스가 어디에서 생성되는지 몰랐기에

page1.vue에서 import { accountStore } 를 하는 순간 생성되는걸로 착각했다.

그렇다면 page2.vue를 생성해 import를 또 하면 새로운 store 인스턴스를 참조하는건가?  그러면 global하게 관리 안되는거 아닌가?

라는 의문의 의문을 낳았지만, store-accesor를 말 그대로 접근하기 위한 만들어진 객체이며 store instance는 nuxt의 내부 기능(store 자동 정의)와 store/index.ts를 이용해 이미 생성되어 있었던 것이다. (그러므로 page component 사이에도 공유가능)

 

Nuxt를 안쓰는 곳에서는 어떻게 Composition API를 쓰면서 어떻게 Vuex를 type-safe하게  쓸 수 있을까?

https://www.npmjs.com/package/vuex-module-decorators

 

vuex-module-decorators

Decorators to make class-like Vuex modules. Latest version: 2.0.0, last published: 3 months ago. Start using vuex-module-decorators in your project by running `npm i vuex-module-decorators`. There are 137 other projects in the npm registry using vuex-modul

www.npmjs.com

위의 문서를 참고하면서 nuxt말고 그냥 vue에서도 vuex-module-decorators는 쓸 수 있다.

 

Vuex를 안 쓰고 store를 type-safe하게 만드는 방법

Vue.observable? Vue.js2.6에서 새롭게 추가된 API
https://kr.vuejs.org/v2/api/index.html#Vue-observable

 

API — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

우리가 data에서 변수를 넣어 리액티브하게 사용하는 것처럼 외부에서 리액티브하게 선언한 변수를 주입해서 작은 store를 만들 수 있다.
즉... 이것을 이용함으로써 Vue.js의 computed이나 render로부터 변경을 검지할 수 있는 오브젝트를 외부에 생성할 수 있게 된다는 것

 

애초에 vuex와 typescript 호환성이 나쁘다는 점을 아예 vuex를 사용안함으로써 배제하고 시작하는것이다.

참고

https://qiita.com/mugi_uno/items/cb48e5d3178891f94fa7

 

Vue.observable & TypeScriptで手早く安心できる状態管理を手に入れる - Qiita

Vue.jsにおける状態管理方法として何を使っているでしょうか。 dataにつっこむ ReduxとかMobXとか といった方法もありますが、もっともメジャーなものはVuexでしょう。 Vuex&TypeScript...

qiita.com

typescript을 적용하기에는 무리없이 가능하지만, 이 방법은 import 하는 순간 인스턴스가 생성되는 것이라 완전 글로벌하게 관리하려면 다른 방법들이 필요하다.

 

Composition API에서 Vuex를 안 쓰고 store를 type-safe하게 만드는 방법

Composition API에서는 ref,reactive 라는 친구들을 Vue.observable 대신에 이용하고 provide, inject를 이용해 글로벌하게 관리할 수 있다. (Vue3가 되면 Vuex는 안써도 된다는 말이 왜 나왔는지 이해할 수 있다.)

참고

https://qiita.com/tmy/items/a545e44100247c364a71

 

Vue Composition API を使ったストアパターンと TypeScript の組み合わせはどのくらいスケールするか?

Vue.js の公式ドキュメントには「状態管理」という章があり、そこでは単純なストアパターンと、より大規模向けという Vuex ライブラリを使う 2 つの手法が紹介されています。 ですが、それ

qiita.com

Comments