woolta

Vue 3.0 에서는 무엇이 바뀔까?

wooltaUserImgvue | 2019-06-18

들어가며..

최근 Vue 를 공부하게 되면서 Vue의 다음 메인 버전인 3가 출시예정이라는 소리를 듣고 기존 대비 어떤것들이 변화되는지 궁금해서 몇가지 찾아보게 되었습니다. Vue 3 버전에 모든 바뀐 부분을 작성한것이 아니고 출시 될때 지금의 내용과는 변경될 수 있습니다.!!

GoodBye reactivity caveats

Vue 2.x 버전Object.definePropertygetter / setter 를 활용하여 속성의 변경이 되도록 구현하였습니다. 그러나 이는 JavaScript의 한계 (ps. Object.observe의 포기) 로 인해 속성을 추가 하거나 **제거 **하는 부분 을 감지할수가 없습니다. 이를 감지하려면 Vue.set 메소드를 통하여 추가해주어야 하였습니다.

Vue 2.x 에서 set을 활용한 속성 추가 및 삭제 방법

// SomeObj 에 hello 라는 키에 world 라는 값을 추가합니다. Vue.set(this.SomeObj, 'hello', 'world'); // SomeObj 의 hello 라는 키를 삭제 합니다. Vue.delete(this.SomeObj,'hello');

Object.defineProperty 에서 proxy 로 변경

Vue 3 에서는 Object.defineProperty 가 아닌 es2015proxy 로 변경하여 구성되었습니다. 이로 인해 속성의 추가 or 삭제감지가 가능하게 되었습니다.

Vue 3 속성 추가 및 삭제 방법

const key = 'hello'; // SomeObj 에 hello 라는 키에 world 라는 값을 추가합니다. this.SomeObj[key] = 'world' // SomeObj 의 hello 라는 키를 삭제 합니다. delete this.SomeObj[key] = 'world'

Vue 3 에서는 더이상 Set 같은 별도의 메소드를 사용하여 추적을 할 필요가 없습니다. :)

Multiple 루트 노트 구성

기존 Vue 2.x 에서는 한 template 안에 루트 노드는 1개만 가능하였습니다.

/// 에러 뿜뿜.. <template> <div></div> <div></div> <div></div> <template/>

Vue 3 부터는 다음과 같이 멀티 루트 노드 구성이 가능합니다.!

/// OK <template> <div></div> <div></div> <div></div> <template/>

더욱 간결해진 Transparent wrappers

그동안 Vue 에서는 컴포넌트 래핑을 위해 Transparent wrappers Pattern 을 통해 다음과 같이 컴포넌트를 래핑해서 사용하였습니다. Transparent wrappers Pattern 의 자세한 설명은 Transparent wrappers Pattern 알아보기 를 봐주세요.

input 래핑 컴포넌트

<template> <label> {{label}} <input v-bind="$attrs" v-on="listeners"/> </label> </template> <script> export default { name: 'BaseInput', inheritAttrs: false, props: { label: { type: String, default: '', }, }, computed: { listeners() { return { ...this.$listeners, input: e => this.$emit('input', e.target.value) } } } }; </script>

다음과 같이 속성이벤트 리스너input에 직접 바인딩 함으로 써 부모에서 사용할때는 다음과 같이 직관적으로 사용할 수 있습니다.

래핑 컴포넌트 사용

<template> <div class="base-test"> <base-input for="baseInput" placeholder="placeHolder입니다." @focus="focus" v-model="inputValue"/> </div> </template>

몹시 편하고 간결하지만 래핑 컴포넌트를 보면 다른 래핑 컴포넌트를 만들때도 몇가지 중복되는 점이 보이실 겁니다.

래핑 컴포넌트 중복점

  1. inheritAttrs 속성을 false 로 설정해 루트 노드가 바로 속성을 못받도록 처리
  2. $attrs 속성을 실제로 받을 노드에 바인딩
  3. $listeners 속성을 이벤트에 받을 노드에 바인딩 (model 이벤트를 추가하여)

이를 더욱 간결하기 위해 Vue 3 에서는 다음과 같이 구현합니다.

래핑 컴포넌트 ( Vue 3 버전)

<template> <label> {{label}} <input v-bind="$attrs"/> </label> </template> <script> export default { name: 'BaseInput', props: { label: { type: String, default: '', }, }, }; </script>

위의 코드를 보면 기존 코드 대비 상당히 간단하게 변경되었습니다. 나머지 모든 옵션 주입은 사라지고 단순히 $attrs 속성만 주입해주면 나머지는 Vue 가 알아서 처리해줍니다.

어떻게 저게 가능하지? how??

이런일이 가능한 이유는 몇가지 속성정보들이 바뀌었기 때문입니다. 이를 자세히 알아봅시다.

속성 inHeritance 의 루트노드 자동바인딩 삭제

  • $attrs 는 props로 지정하지 않은 속성들을 포함하고 있는 속성입니다. 이를 Vue 2.x 에서는 기본적으로 루트노트에 자동으로 바인딩 해주고 있었습니다. 이는 inheritAttrs 속성의 기본값이 TRUE 로 설정되어 있어 가능했던 부분입니다. 이제 Vue 3 에서는 자동으로 바인딩을 해주지 않기 때문에 반드시 지정해 주어야 합니다.

$attrs 은 emit으로 지정하지 않은 모든 이벤트를 포함합니다.

  • Vue 3에서는 $attrs 속성에 emit 으로 지정되지 않은 모든 listeners 까지 포함합니다. 이제 더이상 $listenersv-on 에서 .native 는 사용하지 않아도 됩니다.

v-model will compile to attributes

  • v-modelattributes 에서 컴파일 하기때문에 더이상 input네이티브 이벤트오버라이딩 하거나 model option을 사용한해도 $attrs 만 지정해 주면 됩니다.

faster

Virtual DOM 성능향상

Virtual DOM implementation re-written from the ground up

Virtual DOM 를 처음부터 다시 설계하여 기존 2.x 버전 대비 mountingpatching 작업시 100% 이상 빠르게 동작 하도록 개선되었습니다.

메모리 최적화 및 성능 향상

https://image.woolta.com/3fe798d3fbd07267.png

vue 3.0 에서는 Object.defineProperty 을 활용한 reactivity system 에서 es2015proxy 로 메커니즘을 변경하면서 기본 버전 대비 메모리는 절반으로 사용하고 속도는 두배가량 증가하였습니다.
(Vue 2.5 기준 3000 개의 컴포넌트 인스턴스로 측정한 결과 )

좀더 작은 사이즈

기존의 런타임시 20kb 였던 core gzipped 용량이 약 10KB 까지 감소되었습니다.

더욱 강해진 TypeScript 지원.

vue 에서 매핑 핼퍼 들과 propsTypeScript 로 제대로 지원을 못해주어서 TypeScript 를 쓰기 되게 힘들었으나 Vue 3 에서 부터는 다음과 같이 TypeScript 를 지원합니다.

interface BaseProps { text: string } class BaseComponent extends Component<BaseProps> { render() { return <div> {this.$props.text} </div> } }

IE 호환성

Vue 3 부터는 IE11 부터 지원 하도록 변경되었습니다.

참고