Vue3로 더 빠른 웹 애플리케이션

업데이트: Link

Vue3로 더 빠른 웹 애플리케이션

Written by Filip Rakowski

우리는 Vue.js의 다가오는 세 번째 주요 릴리스에 대해 점점 더 많이 듣는 경향이 있습니다. 토론을 통해 아직 모든 것이 확실하지는 않지만 현재 버전(이미 뛰어난)보다 크게 개선될 것이라고 안전하게 가정할 수 있습니다.

Vue 팀은 프레임워크 API를 개선하는 놀라운 일을 하고 있습니다. Evan You는 Vue 3의 목표를 다음과 같이 설명했습니다.

  • 더 빠르게
  • 더 작게
  • 더 유지 보수가 쉽게
  • 더 쉽운 네이티브 타겟팅
  • 더 당신의 삶을 쉽게

그리고 RFC와 대화를 보면 위의 모든 목표가 문제 없이 달성될 것이라고 확신합니다. 이 기사에서는 그 영향과 가능성 측면에서 가장 흥미로워 보이는 몇 가지 변경 사항을 안내해 드리고자 합니다.

성능 최적화

특정 API를 파헤치기 전에 성능 괴물로서 Vue 3의 성능에 대해 이야기할 것 입니다. 그리고 할 얘기가 많습니다! 거의 모든 면에서 상당한 개선 사항을 찾을 수 있습니다!

Vue 3의 번들 크기부터 시작하겠습니다.

현재 축소 및 압축된 Vue 런타임 가중치는 약 20kB(현재 2.6.10 버전의 경우 22.8kB)입니다. Vue 3 번들은 무게가 절반 정도인 것으로 추정되므로 ~10kB에 불과합니다!

글로벌 API 트리 쉐이킹

더 나은 모듈화 Vue 3 소스 코드와 같은 많은 최적화 기능 외에도 트리 셰이커블이 있습니다. 즉, 일부 기능(예: keep-alive 구성요소 또는 v-show 지침)을 사용하지 않으면 해당 기능이 제품 번들에 포함되지 않습니다. 현재는 Vue core에서 어떤 기능을 사용하든 간에 Vue 인스턴스가 단일 개체로 내보내지고 번들러가 코드에 사용된 개체의 속성을 감지할 수 없기 때문에 프로덕션 코드에 포함됩니다.

 // Vue 2.x - whole `Vue` object is bundled for production 
import Vue from 'vue'

Vue.nextTick(() => {})
const obj =  Vue.observable({})

글로벌 API 트리 셰이커블 Vue 팀은 번들러가 사용되지 않는 코드를 감지하고 제거할 수 있도록 명명된 내보내기를 통해 이들 중 대다수를 가져오기로 결정했습니다.

 // Vue 3.x - only imported properties are bundled
import { nextTick, observable } from 'vue'

nextTick(() => {})
const obj = observable({})

기존 글로벌 API는 명명된 내보내기를 통해서만 사용할 수 있게 되므로 이는 획기적인 변화입니다. 이 변경 사항은 다음과 같습니다.

  • Vue.nextTick
  • Vue.observable
  • Vue.version
  • Vue.compile (only in full builds)
  • Vue.set (only in 2.x compatibility builds, you’ll find out soon why)
  • Vue.delete (same as above)

이 기능은 업계의 생태계에서 채택해야 하기 때문에 이 기능을 완전히 활용할 수 있으려면 시간이 걸릴 것입니다. Vue 팀은 호환성 빌드를 릴리스할 예정이므로 이전 API를 사용하는 플러그인도 사용할 수 있지만 성능 저하가 있습니다.

트리 셰이커블에는 JavaScript API가 더 있습니다. 후드 Vue 컴파일러(Vue 템플릿을 렌더링 함수로 변환하는 도구) 아래에서 템플릿에 사용되는 지시어를 감지하고 이를 트리 셰이크합니다. 아래 템플릿의 예:

<transition>
  <div v-show="ok">hello</div>
</transition>

Vue 컴파일러에서 처리한 후 다음과 같이 표시됩니다.

import { h, Transition, applyDirectives, vShow } from 'vue'

export function render() {
  return h(Transition, [
    applyDirectives(h('div', 'hello'), this, [vShow, this.ok])
  ])
}

누구나 글로벌 API 트리 쉐이킹(특히 사용자)의 혜택을 받겠지만, 작고 가벼운 웹 사이트를 만들고 상호 작용에 대해 일부 Vue 기능만 사용하는 jQuery와 같은 라이브러리를 대체하는 사람들이 가장 중요하게 여길 것이라고 생각합니다.

프록시 기반 반응성

번들 크기는 애플리케이션 로딩 시간에 큰 영향을 줄 수 있지만 다운로드 후에는 렌더링 속도가 빨라지고 성능이 원활해야 합니다.

Vue core 팀은 이러한 사실을 매우 잘 알고 있으며, 이것이 런타임 성능도 크게 향상되는 이유입니다.

JavaScript Proxies를 기반으로 하는 가장 영향력 있는 새로운 반응성 시스템 중 하나부터 시작하겠습니다. 현재 Vue 반응성 시스템은 Object.defineProperty를 기반으로 하고 있으며, 몇 가지 제한 사항이 있습니다. 가장 일반적이고 실망스러운 것은 Vue가 반응 객체의 속성 추가/삭제를 추적할 수 없음입니다. 반응 시스템이 의도한 대로 작동하도록 하려면 이 목적을 위해 Vue.setVue.delete를 사용해야 했습니다. JS Proxies를 사용하면 마침내 이 추악한 해결 방법을 제거할 수 있습니다.

// Adding a new property to reacitve object in Vue 2.x
Vue.set(this.myObject, key, value) 
// Adding a new property to reactive object in Vue 3
this.myObject[key] = value

프록시의 실제 영향은 훨씬 빠른 구성 요소 초기화 및 패치에서 확인할 수 있습니다. 테스트에 따르면 약 2배 더 빠릅니다!

이 개선의 이유는 getter/setter를 사용하여 Vue가 모든 객체와 속성을 재귀적으로 살펴보고 변환해야 했기 때문에 특히 중요합니다. 프록시를 사용하면 이 프로세스가 훨씬 쉽습니다.

JS 프록시를 사용하면 Vue 3에서 Internet Explorer(Edge 아님)에 대한 지원이 중단되지만 걱정하지 마십시오. IE를 지원하려는 사람들을 위한 호환성 빌드가 있을 것입니다.

Time slicing

업데이트 Evan You의 트윗에 따르면 이 기능은 Vue 3에 포함되지 않습니다.

Vue 3의 정말 흥미롭지만 거의 언급되지 않는 또 다른 성능 기능은 Time Slicing에 대한 실험적 지원입니다.

타임 슬라이싱이 무엇인지 설명하기 위해 비유를 사용하겠습니다. 아이스크림 라인을 상상해 보시길 바랍니다. 매우 긴 것입니다. 왜냐하면 그것이 마을에서 가장 좋은 아이스크림이기 때문입니다. 한 사람이 서빙된 후에는 다른 사람이, 또 다른 사람이 제공되는 등입니다. 그리고 어떤 이유로 사용 가능한 맛에 대한 정보가 없습니다. 이 정보를 얻으려면 아이스크림을 직접 파는 아주머니에게 물어봐야 합니다.

이러한 상황에서 우리는 아마도 2개의 라인으로 끝날 것입니다. 하나는 아이스크림을 사고 싶다고 확신하는 사람들을 위한 것이고(인내심을 갖고 기다리는 사람들을 위한 것입니다), 다른 하나는 아이스크림을 살 것인지 결정하기 전에 맛에 대해 더 많은 정보를 원하는 사람들을 위한 것입니다. 아니다. 최신 정보는 가능한 한 빨리 얻어야 합니다. 불행히도 아이스크림을 파는 여성은 단 한 명뿐이며 “메인” 라인의 모든 고객에게 서비스를 제공하기 전에 어떤 질문에도 대답하지 않습니다.

이것은 아직 확신을 갖지 못한 고객에게 최고의 경험이 아니며 대부분의 고객은 기다릴 가치가 없다는 것을 알게 될 것입니다. 이 문제를 해결하기 위해 여성은 2-3명의 고객에게 서비스를 제공할 때마다 하나의 질문에 답할 수 있었습니다. 두 그룹 모두 이 솔루션에 만족해야 합니다.

이것이 바로 CPU가 웹 앱에서 작동하는 방식입니다. 사용자 상호 작용에 응답하기 전에 모든 주요 작업(스크립팅, 렌더링 등)을 수행해야 하는 “메인” 라인(“메인 스레드”라고 함)이 있습니다. 일부 페이지의 경우 Vue 구성 요소를 로드하거나 다시 렌더링하는 데 걸리는 시간에 따라 매우 나쁜 사용자 경험을 초래할 수 있습니다.

더 신뢰할 수 있게 하려면 이 스크립트 평가를 조각으로 “잘라내고” 각 평가 후에 처리할 사용자 입력이 있는지 확인하는 것이 훨씬 좋습니다. 이런 식으로 앱은 얼마나 많은 렌더 또는 재렌더링이 필요한지에 관계없이 응답성을 유지합니다. 이것이 Vue 3에서 작동하는 방식입니다.

이것이 Evan You가 Vue 3에서 Time Slicing 기능을 제시한 방법입니다. 스크립트 실행 타임라인의 작은 차이를 발견하여 사용자 입력을 처리하기 위한 것입니다.

Photo from Vue Mastery

구성 요소가 다시 렌더링되는 이유를 쉽게 식별하는 기능

도구는 기본 성능만큼 중요합니다. 이에 따르면 Vue 3 - renderTriggered에서 새로운 라이프사이클 후크를 볼 수 있습니다. 이를 사용하여 불필요한 구성 요소 재렌더링을 추적하고 제거할 수 있습니다. 이는 타임 슬라이싱과 결합할 때 런타임 성능 최적화에서 매우 강력한 무기입니다.

const Component = {
  // other properties
  renderTriggered (event) {
     console.log(`Re-render of ` + this.$options.name + ` component`, event)
  }
}

What else

Vue 3에서 본 것보다 훨씬 더 많은 것이 있지만 아마도 가장 영향력 있는 변경 사항일 것입니다. 언급되지 않은 개선 사항의 대부분은 Vue 컴파일러에서 생성한 코드에 숨겨져 있거나 구현 세부 정보 및 알고리즘과 관련이 있습니다.

그러나 다음과 같은 몇 가지 개선 사항을 언급할 필요가 있습니다.

  • 출력 코드는 JavaScript 컴파일러에 대해 최적화하기가 더 쉬울 것입니다.
  • 출력 코드는 일반적으로 훨씬 더 최적화됩니다.
  • 패치 알고리즘 개선으로 불필요한 부모/자식 재렌더링이 방지됩니다.

또한 앞으로 Evan You에서 Vue 컴파일러를 위해 특별히 만든 성능 최적화에 대한 자세한 기사를 볼 수 있습니다.(게시되면 링크로 기사를 업데이트하겠습니다.)

요약

Vue는 이미 최고의 성능을 발휘하는 프레임워크 중 하나로 자리 잡았지만 3번째 릴리스에서는 특히 번들 크기와 런타임 성능에서 크게 개선될 것입니다. 또한 무수히 많은 마이크로 최적화가 이루어졌습니다. Vue 3는 현대의 모바일 우선 및 성능 지향 웹에 완벽하게 들어맞는다고 생각합니다.

Vue는 커뮤니티에서 완전히 주도하는 유일한 주요 프레임워크라는 것을 잊지 마십시오. 이 문서에 나열된 모든 변경사항(및 기타 사항)은 RFC의 형태로 논의됩니다 여기 커뮤니티와 함께 합니다. 핵심 팀을 돕고 활성 RFC에 대한 의견을 표현하거나 자체 개선 사항을 제안할 수도 있습니다. Vue를 함께 개선합시다! 😉

What’s next

다음 기사에서는 새로운 Vue 3 API가 웹 앱을 작성하는 방식에 어떤 영향을 미치는지 살펴보겠습니다. 최근에 인기 있는 컴포지션 API를 비롯한 다양한 API를 살펴보고 이를 사용하여 더 우수하고 유지 관리하기 쉬운 코드를 작성하는 방법을 알아보겠습니다.

댓글남기기