[Vue.js] vuex 를 이제 안쓴다고?(Pinia) vue2, vue3 차이점

cgoing·2023년 6월 5일
11
post-thumbnail

소개 👶

원본글

최근 vue2 -> vue3,nuxt3 로 마이그레이션 하는 프로젝트들이 제법 많이 보이곤 합니다.
vite, ts, composition api 등이 도입 되며, 성능, 개발환경,코드 스타일 말이 안되게 좋아졌습니다 👏👏
또한 vutify 의 vue3 지원과, nuxt3 의 vue3 지원등 이러한 업그레이드 들이 안정화 까지 마친 시점 이라고 생각합니다.
그리고 또한 vue2 의 지원이 2023년 12월 31일 부로 종료 됐기도 합니다.


목차

vue3 한국어 공식문서
1. vite
2. 상태 관리 vuex -> Pinia
3. typescript
4. react 와 비교 (Composition API)


Vite

Vite는 Evan You(유인동), Vue.js의 창시자가 만든 최신 웹 개발 빌드 도구입니다. Vite는 프랑스어로 "빠른"을 의미하며, 그 이름에서 알 수 있듯이 빠른 개발 서버 시작, 빠른 뜨거운 모듈 재 로딩(HMR), 빠른 프로덕션 빌드 등을 목표로 합니다.

Vue CLI는 웹팩을 사용하여 트랜스파일링과 핫 스왑을 통해 코드를 브라우저에 맞게 변환합니다. 이는 개발 프로세스를 매끄럽게 하지만, 모든 변경사항에 대해 트랜스파일링과 핫 스왑을 수행해야 하므로 시작 시간이 상당히 길고, 개발 중 재컴파일 시간이 필요 이상으로 길어집니다

반면에 Vite 는 트랜스파일링을 전혀 사용하지 않고 ECMAScript 6의 모듈 지원을 이용합니다. 이는 브라우저가 필요에 따라 모듈을 검색하게 해주므로, 프로젝트를 개발하는 동안에는 빌드하지 않아도 되며, 시작 속도와 컴파일 시간이 크게 줄어듭니다. 그러나 이러한 이점을 얻기 위해선 개발 중에 최신 브라우저를 사용해야 합니다​. ( 익스플로어 11 지원 안됨 )

채감상 컴파일시간이 4배 ~ 8배 정도 빠름


vuex 를 사용하지 않는다고??

react는 다양한 상태관리 라이브러리 들이 많죠, 대표 적으로 redux, recoil 등.. 하지만 vue는
지금까지 vuex 원툴 이였습니다. 사실 상태관리 모듈을 별도로 install 하지 않고 굉장히 쉽고 간단하게 직접 구현하거나 composition API 로 전역상태를 관리 할 수 있습니다.

// store.js  composition API 
import { reactive } from 'vue'

export const store = reactive({
  count: 0,
  increment() {
    this.count++
  }
})

... 
// 전역상태를 사용할 componenet 에서 
<script setup>
import { store } from './store.js'
...
</script>

<template>
  <button @click="store.increment()">
    B 컴포넌트에서: {{ store.count }}
  </button>
</template>

물론 추론이나 dev Tools 과 같은 helper 들, 또 스토어 규모,팀 규모 가 커질수록 코드 컨벤션, 규칙 때문에라도 무조건 외부 모듈을 install 하는게 좋습니다.

vue3 공식문서에 보면 공식 상태관리 라이브러리 피니아(Pinia) 라고 작성되어 있습니다.
Vue 핵심 팀이 유지 관리하며 Vue 2 및 Vue 3에서 모두 작동합니다.

기존 Vue 사용자는 이전 공식 상태 관리 라이브러리인 Vuex에 익숙할 수 있습니다. Pinia가 생태계에서 동일한 역할을 수행하면서 이제 Vuex는 유지 관리 상태에 있습니다. 여전히 작동하지만 더 이상 새로운 기능이 추가되지 않습니다. 새로운 앱에는 Pinia를 사용하는 것이 좋습니다.
Pinia는 Vuex 5의 핵심 팀 논의에서 나온 많은 아이디어를 통합하여 Vuex의 다음이 어떤 모습일지 탐구하는 것으로 시작했다. 결국 우리는 Pinia가 이미 Vuex 5에서 원하는 것을 대부분 구현하고 있다는 것을 깨닫고 이것을 새로운 권장 사항으로 적용하기로 결정했습니다.
Vuex와 비해 Pinia는 더 간단한 API를 제공하고, Composition-API 스타일의 API를 제공하며, 가장 중요한 것은 TypeScript와 함께 사용할 때 견고한 유형 추론을 지원합니다.

  1. 타임라인, 컴포넌트 검사, time-travel 디버깅을 포함하여 Vue 개발자도구와 통합
  2. 핫 모듈 교체(HMR)
  3. 서버 사이드 렌더링 지원 (Nuxt.js)
  4. 훨씬 가벼움

vuex 보다 더 사용하기 용이 하고 그냥 composition API 그대로 사용하는 느낌입니다.

// 기존 vuex 와 같은 형태 처럼 사용하는 option Store
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0, name: 'Eduardo' }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

// compositionAPI 를 그대로 사용 할수 도 있습니다.  이건 사실 pinia 가 없어도 가능하지만, devTools 때문에 ..?  
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const name = ref('Eduardo')
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, name, doubleCount, increment }
})


// 사용할때 

<script setup>
	const store = useCounterSotre(); 
   //  ...  
</script>

defineStore 의 첫번째 인자 인 key 는 devTools 에서 사용됩니다.
기존에 vuex 에서도 store mutation 에 타임라인을 제공했었나 기억이안나네... 무튼 redux Toolkit 처럼 store timeline 이 제공 됩니다.

store는 reactive로 래핑된 객체입니다. 즉, getter 뒤에 .value를 쓸 필요가 없지만, setup의 props와 같이 구조화할 수 없습니다

구조분해를 하게되면, 반응성을 읽는다는 말인데요 그 이유는 composition api 의 ref() 같은 옵저버 상태로 만드는 함수들은 js 의 Proxy 객채로 감싸져 있기 때문입니다.

//  setup 에서의 props 를 디스트럭처링  하면 반응성을 읽게 되는 이유 

const proxy = new Proxy( {name:'cgoing',age:30},{
	get(t,k){ return t[k] + new Date() }
})

console.log(proxy.name) // 'cgoing 콘솔로그 한 시점의 시간으로 계속 바뀜' 

const { name } = proxy;
console.log(name) // proxy 에서 name 을 디스트럭처링 한 시점의 시간 이 계속 유지됨 

와 같은 이유로 디스트럭처링을 사용할경우 toRefs() 감싸 주어야 합니다.

// 직접적으로 store 를 참조하면 increment 로 인한 증감된 count 는 반응성이 유지됨 
<template>
  {{ store.count }}
  <v-btn @click="store.increment" />
</template>

<script setup lang="ts">
import { useCounterStore } from "./store/app";

const store = useCounterStore();
</script>


// 디스트럭처링을 할 경우 반응성을 읽기 때문에 toRefs 로 감싸줘야함 
<template>
  {{ count }} // 반응성이 없기때문에 변하지 않음
  {{ refCount }} // 변함 
  <v-btn @click="increment" />
</template>

<script setup lang="ts">
import { toRefs } from "vue";
import { useCounterStore } from "./store/app";

const { count, increment, $state } = useCounterStore();
const { count: refCount } = toRefs($state);
</script>



[options][setup()없이 사용하기](https://pinia.vuejs.kr/cookbook/options-api.html)


typescript 😍

저는 Nest.js 때문에 (Nest.js 는 데코레이터(java의 어노테이션 같은) 기반 node server framework) 강제로 typescript를 배우게 됐었는데요, 원래 java base 로드맵을 거쳤기 때문에 타입과 추론은 잘 이해하고있었습니다. ts 를 한번 사용하고나니 아주 작은 util 을 만들어도 ts로 만들고 싶어지더라구요.. 프로젝트에서 어쩔수없이 js 를 사용하게된다면 JS DOC 이라도 사용했습니다.. 무튼 사랑해 ts

typescript 정식적으로 지원되며, defineComponent 와 같은 추론을 위한 장치 들이 나왔습니다.
.vue 파일에 사용하기위해 아래 처럼 lang='ts' 를 명시 해야합니다.

<script setup lang="ts">
	cosnt count = ref<number>(0);
 // react ts 와 유사함     const [state,setState] = useStaste<number>(0)
... 

react.js 와 비교

vue3 에서 Composition API 가 정식적으로 번들링에 포함되면서
react 와 가까운 코드 스타일 작성이 가능해졌습니다.

react 에서 파생된 hook 스타일 이라던가 (vue에선 컴포져블 이라고 표현 )


// vue.js 	

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 관례상, 컴포저블 함수 이름은 "use"로 시작합니다.
export const useMouse()=> {
  // 컴포저블로 캡슐화된 내부에서 관리되는 상태
  const x = ref(0)
  const y = ref(0)

  // 컴포저블은 시간이 지남에 따라 관리되는 상태를 업데이트할 수 있습니다.
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 컴포저블은 또한 이것을 사용하는 컴포넌트의 생명주기에 연결되어
  // 사이드 이펙트를 설정 및 해제할 수 있습니다.
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 관리 상태를 반환 값으로 노출
  return { x, y }
}



//react 


export const useMouse()=> {
  // 컴포저블로 캡슐화된 내부에서 관리되는 상태
  const [x,setX] = useState(0)
  const [y,setY] = useState(0)

 
  function update(event) {
   setX(event.pageX)
   setY(event.pageY)
  }

  useEffect(()=>{
		window.addEventListener('mousemove', update);
	return ()=>window.removeEventListener('mousemove', update)
  },[])

   return  { x , y }
}

외에도 useRouter, useStore 등 react 에서 먼저 시작된 use 라는 네이밍 관습을 따라하는 모습이 보여집니다.

사실 vue2 =>vue3 의 핵심은 composition API 입니다. 그래서 많은 것들이 composition API에 맞춤되어 변경 된 걸 확인 할 수 있는습니다.

해당 포스트에선 composition API 에 대한 내용은 다루지 않았기때문에 혹시 잘 모르신다면 찾아보시길 바랍니다.


마무리

이 외에도, Suspense 컴퍼넌트 라던가 ( async Compoenent (async setup() )를 위한 ), Teleport Component , scss 등 다양한 신규 아이템 들이 존재합니다.
vue 공식문서 한글 번역이 너무 잘되어있기 때문에 직접 읽어보시면 좋을 것 같습니다.

Nuxt 3 도 안정화가 많이 된 것 같아 보이니 공식 문서를 통해 읽어보시면 좋을것 같아요

결론

기회가 된다면 꼭 vue3 로 마이그레이션 ( 혹은 신규 개발인데 이유없이 vue2로 한다고하면 )을 시도해보세요. 그게 곧 그 프로젝트의 가장 큰 기여가 될 것 입니다.

profile
사랑해

2개의 댓글

comment-user-thumbnail
2023년 6월 7일

Vue3 소개 글인데 마무리는 Next.js ㅠㅠ

1개의 답글