벌써 1년차가 되었읍니다.. 정신없이 보냈지만 그 사이에 세상은 빠르게 변했고, 내 vue2 코드는 레거시 코드....로 변모 중 입니다. vue3가 기본 버전으로 채택 되면서 vue2 -> vue3에 달라진 점을 간략하게 정리해보겠습니다.
고작 1년차 개발자이지만 기술이 정말 빠르게 변한다고 피부로 느끼고 있다. 프론트엔드의 3대 생태계 리액트, 뷰 , 앵귤러에서 엥귤러는 속도가 무섭게 외면받고 있고, 리액트와 뷰와는 다른 메커니즘의 형태인 스밸트(Svelte)가 주목받으며 생태계를 넓혀가는 중 이고, 영원한 상태관리의 왕인 줄 알았던 리덕스를 대항 할 리코일(Recoil)의 주목으로 다른 형태의 상태관리 방법이 등장하는가 하면, 급 부상한 RX(ReactiveX)의 주목으로 반응형 프로그래밍은 대부분 기업에서 채택하여 사용하고 있는 기술이 되었다. (RX는 플러터를 공부하다 처음 접해봤는데 꽤나 재미있는 주제이다.)
React는 업데이트를 통해 ssr을 지원하게 되었고, vue는 3버전으로 올라가면서 타입스크립트 도입의 제약이 사라졌다. 이렇게 빠르게 변화하는 세상속에서 개발자의 삶이란 평생 공부할 수 밖에 없는 숙명이다.. 그래서 결론이 뭐냐? 코어 개념의 중요성이다~
실무에서는 vue2가 압도적으로 많이 사용하고 있고, 커뮤니티나 라이브러리 생태계도 아직은 vue2를 기반으로 형성되었기 때문에 vue3를 바로 적용하기는 힘들테지만 그래도 미리 정리해 두자
Composition api의 등장이 가장 큰 변화
Composition api의 사용으로 vue에서의 코드가 react에서의 hooks사용과 많이 닮아가는 모습이지만, 내부의 코드의 가독성이 월등하게 높아 질 수 있을 것 같다.
vue는 비지니스 로직이 method, watch, computed에 흩어져 한눈에 파악하기 힘들어 지는 경향이 있다. 그렇기에 내부 컨벤션을 확고하게 정해두고 만들지 않으면 이곳 저곳에 퍼져있는 팔로우하며 파악해야 하는데, 그러한 점을 composition api를 통해 모듈화 하여 사용할 수 있게 되면서 별도의 컨벤션 없이 묶음으로써 관리가 가능해졌다.
예시 (공식문서)
<!-- MyBook.vue -->
<template>
<div>{{ readersNumber }} {{ book.title }}</div>
</template>
<script>
// react hooks와 유사하게 선언을 통해 가져옴
import { ref, reactive } from 'vue'
export default {
//새로생긴 함수 init과 유사
setup() {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// 템플릿에 노출
return {
readersNumber,
book
}
}
}
</script>
기존의 data, method 등의 선언이 전부 setup이라는 메소드 안으로 편입 되었다. setup 내부에 state와 method를 선언 하게 되면서 기존에 흩어져있던 계층을 하나로 합친 느낌이다. react와 매우 유사하게 변하였다.
import { reactive, computed } from 'vue'
export default {
props: {
title: String
},
//새로운 setup
//새로운 props 할당, emit 관리
setup (props, { emit }) {
// 새로운 reactive객체 생성
const state = reactive({
username: '',
password: '',
//새로운 computed 사용 방법
changedComputed:computed(() => state.username.toChangedMethod())
})
const login = () => {
// login method
}
return {
login,
state
}
}
}
기존의 vue 2
export default {
data (){
return {
username: '',
password: '',
}
},
computed: {
lowerCaseUsername () {
return this.username.toLowerCase()
}
},
watch:{},
methods: {
login(){
// login method
}
}
}
computed의 선언도 setup내부로 편입되어지면서 한눈에 팔로우가 한결 수월해진 모습
setup의 파라미터로 props와 emit을 받게 된다. 이러한 형태로 emit을 한군데 모아 관리할 수 있게 되었다.
watch메서드는 복수의 값을 관리 가능 하게 되었고, watch를 중단하거나 watchEffect를 통해 사이드 이펙트를 여기서 관리할 수 있게 됌(구조분해할당 안해도 됌).
여기서 state에 갑자기 reactive라는 객체를 생성하게 되는데(getter, setter), 기존에 vue2의 경우에는 이러한 과정이 없었다. 이 플로우에 대한 공식문서의 설명
Vue2 에서는 data나 method, computed 등을 선언하게 되면 알아서 각각에 대해 위와 같이 동작하는 reactive 객체를 생성하였습니다. 하지만 그 과정이 묵시적이었고, 유저들은 위 과정을 알 필요가 없었습니다. 하지만 Vue3에서의 타입스크립트의 지원이나 state로의 명칭 변경, 명시적 reactive 사용 등을 보았을 때, 전반적으로 명료한 선언을 지향하는 방향으로 변화한 것으로 보입니다.
이 부분도 정말 시급했던 부분인데, 이제 아무 기능 없는 div태그가 필요 없게 되었다. 루트에 여러개의 컴포넌트 공존 가능
<Fragment>
<button />
<button />
</Fragment> // ok
리액트의 포탈 컴포넌트와 유사. 모달 컴포넌트 활용시 유용하게 사용 가능 할 듯.
app.component('modal-button', {
template: `
<button true>
Open full screen modal! (With teleport!)
</button>
//새로생긴
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button false>
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
출처 vue 공식문서