월간 지앤선

번역: 이상한모임 번역팀

편집: 지앤선 편집장 아델라

 

Vue 2.6 released

 

2019 Feb 4

어제 우리는 the 5th Vueniversary  를 축하했었는데요 —오늘은 Vue 2.6 "Macross"를 선보일 수 있게 되어 몹시 흥분됩니다.

 

 

지난 1년 동안 우리는 새로운 CLI와 3.0용 프로토타이핑에 많은 시간을 할애했습니다. 그로 인해서 오랜 기간 동안 Vue Core 2.X의 주요 업데이트를 하지 못했죠. 때가 되었습니다! 이번 릴리즈에서는 여러 가지의 상당한 개선사항과 내부 변화, 그리고 이 글에서 강조된 새로운 기능들이 포함되어 있습니다. 자세한 내용은 Github의 full release note를 확인하세요.

 

Slots: 새로운 구문, 성능 개선 & 3.0에서의 변화

 

Slots은 Vue에서 유연한 구성을 가능하게 하는 중요한 메커니즘입니다. 3.0을 프로토타이핑하는 동안 이를 개선하기 위한 몇 가지 방법을 찾았습니다. 이 중 몇 가지는 큰 변화 없이 2.x의 minor release에 도입될 수 있습니다. 일부의 개선사항은 변경사항을 위반하게 되므로 향후 마이그레이션을 더 쉽게 할 수 있도록 2.x의 더 나은 대안을 제공하려고 노력하고 있습니다.

 

새로운 구문

 

첫 번째는 scoped slot의 새로운 구문입니다. 우리는 다양한 디자인(1, 2, 3)을 제안하고, 논의하고, 시도해보았고 최종적으로 새로운 v-slot문법을 정했습니다. 여기 RFC에 관련된 설명이 있습니다. 아래는 named slot을 사용하는 간단한 예시입니다:

 

<my-component>
  <template v-slot:header>
    <p>Header</p>
  </template>
  
  <template v-slot:item="{ data }">
    <h2>{{ data.title }}</h2>
    <p>{{ data.text }}</p>
  </template>
  
  <template v-slot:footer>
    <p>Footer</p>
  </template>
</my-component>

컴포넌트에서 여러 개의 named slot과 함께 v-slot을 사용하는 예시

 

새로운 구문은 normal slot과 scoped slot을 하나의 디렉티브에 통합해서 사용하는데, 이로 인해서 named slot을 더 명시적이고 가독성 좋게 사용할 수 있습니다. 그리고 기존 구문과도 완벽히 호환이 되기 때문에, 오늘이라도 2.6 버전으로 옮겨갈 수 있습니다.

여러분이 이미 기존의 slot 구문에 익숙하다면, 우리는 RFC를 통해서 새로운 구문이 만들어진 배경에 대한 이해도를 높이는 것을 추천합니다. 만약 그게 아니라면, RFC 대신에 업데이트된 slot 문서를 보는 것이 좋습니다.

 

더 좋아진 성능

 

3.0에서 선보이고 싶은 slot에 대한 또 다른 개선점은 일반 slot과 scoped slot의 구현 방식의 통일인데요, scoped slot이 성능상의 이점이 있기 때문에 가능한 거죠. 보통 slot은 부모 컴포넌트의 렌더 사이클(render cycle)에 포함되어 표현(render)됩니다. slot의 종속성이 바뀌면, 부모와 자식 컴포넌트 모두를 다시 표현해 주어야 합니다. 하지만 scoped slot에선, 인라인 함수로 컴파일되어 자식 컴포넌트의 렌더 사이클에서 그 함수를 부르게 됩니다. scoped slot에서 데이터 종속성은 자식 컴포넌트에서 모아지고, 더 간결한 업데이트가 가능해집니다.

2.6에서 소개된 하나의 최적화 기능이 있는데요, scoped slot만 사용한 컴포넌트라면, 그 부모 컴포넌트의 종속성 변화(dependency mutation)는 부모에만 영향을 미치고, 자식 컴포넌트 업데이트를 강제로 하게 만들지는 않습니다.

그 외 추가사항:

  • 새로 추가된 v-slot 구문을 사용한 slot은 자체적으로 scoped slot으로 컴파일됩니다. 새로운 구문을 사용하면 자동적으로 성능 향상이 되는 거죠.
  • 기존 slot 역시 this.$scopedSlots에 함수로 표현됩니다. 이제부터는 템플릿 대신 렌더 함수를 사용하는 사용자들은 언제든지 this.$scopedSlots을 사용할 수 있다는 의미가 됩니다. 어떤 종류의 slot이 들어왔는지 고민할 필요 없이 말이죠.

 

3.0에서는, scoped slot과 non-scoped slot의 구분이 사라지게 될 겁니다. 모든 slot은 같은 문법을 사용하고, 같은 형식으로 컴파일되고, 같은 최적화된 성능을 가지게 됩니다.

 

비동기 에러 핸들링

 

Vue의 내장 에러 핸들링 메커니즘(컴포넌트 내의 errorCaptured 훅과 글로벌 errorHandler 훅)은 이제 v-on 핸들러 내에서 발생한 에러도 잡아냅니다. 뿐만 아니라 라이프 사이클 훅이나 이벤트 핸들러를 통해 비동기적인 처리를 한다면 함수에서 프로미스를 리턴할 수도 있습니다. 프로미스 체인에서 잡히지 않았던 에러 또한 에러 핸들러에 보내질 거예요. async/awiat를 사용하면 처리 하기가 훨씬 쉬울 겁니다. async 함수는 암묵적으로 프로미스를 리턴하니까요.

export default {
  async mounted() {
    // if an async error is thrown here, it now will get
    // caught by errorCaptured and Vue.config.errorHandler
		// 만약 여기서 비동기 에러가 발생한다면
		// 이제는 errorCaptured 훅이나 Vue.config.errorHandler에 의해
		// 처리될 겁니다
    this.posts = await api.getPosts()
  }
}

라이프 사이클 훅 내에서의 비동기 에러 핸들링


동적 디렉티브 전달인자

 

이제 동적 전달 인자에 자바스크립트의 동적 표현식을 전달할 수 있습니다.

<div v-bind:[attr]="value"></div>
<div :[attr]="value"></div>

<button v-on:[event]="handler"></button>
<button @[event]="handler"></button>

<my-component>
  <template v-slot:[slotName]>
    Dynamic slot name
  </template>
</my-component>

동적 전달인자 예제

 

보다 상세한 내용은 RFC 문서에서 확인 가능합니다. 편리하게도 전달 인자의 값이 null이라면 바인딩이나 리스너는 제거될 것입니다.

라이브러리 제작자들을 위한 메모: 이 기능은 Vue 런타임 2.6.0 버전 혹은 그 이상에서 지원됩니다. 미리 컴파일된 컴포넌트를 배포하면서 2.6 이전 버전과 호환성도 유지하고 싶다면 소스 코드 내에 이 문법을 포함하지 마세요.

 

컴파일러 경고 메시지 규격

 

Github의 Gzzhanghao라는 사용자가 pull request를 한 덕분에, 2.6 버전부터는 이제 대부분의 템플릿 컴파일 경고에 소스 범위 정보가 제공됩니다. 이 기능은 Vue2.6.0 이상의 버전을 요구합니다. 만약 여러분이 이미 컴파일된 컴포넌트를 적용하고 2.6 버전 이전에 작성된 소스를 유지보수 한다면, 본 버전을 적용 시키지 마세요. 이로 인해 다음과 같은 경고에 대해 양호한 코드 프레임을 생성할 수 있게 되었습니다.

 


Standalone Reactive 객체의 명시적인 생성

 

2.6 버전은 standalone으로 동작하는 객체를 명시적으로 생성하기 위한 새로운 국제 규격 API를 소개합니다.

 

const reactiveState = Vue.observable({
  count: 0
})

 

생성된 객체는 복합 속성 또는 렌더링 함수에서 직접적으로 사용될 수 있으며 소스 변화가 일어나면 적절한 업데이트를 수행합니다.

 

서버 사이드 렌더링 동안 데이터 미리 가져오기

 

새로운 serverPrefetch 은 (단순히 라우트 레벨의 컴포넌트가 아닌) 모든 컴포넌트가 서버 측 렌더링 중에 데이터를 미리 로드할 수 있도록 가져오도록 합니다, 이를 통해 vue를 보다 유연하게 사용할 수 있고, 데이터를 가져오는 것과 라우터 간의 결합도를 낮출 수 있죠. 이미 Nuxt와 vue-apollo 같은 프로젝트들은 이 새로운 기능을 사용하여 구현을 단순화할 계획을 갖고 있습니다.

 

Direct Import를 위한 ES 모듈 빌드

 

이전에는 ES 모듈 빌드가 주로 bundler와 사용하기 위함이었습니다. 이 빌드들은 컴파일 시간에 대체되는 환경변수 사용을 포함합니다. Vue 2.6은 이제 브라우저 안에서 직접 사용을 위한 ES 모듈 빌드도 포함합니다:

<script type="module">
import Vue from 'https://unpkg.com/vue/dist/vue.esm.browser.js'
  
new Vue({
  // ...
})
</script>


중요한 내부 변경 사항

 

nextTick을 Microtask로 다시 변경

 

2.5.0 버전에서, v-on 이벤트 핸들러가 업데이트를 트리거한 경우, Microtasks 대신 nextTick으로 Macrotasks를 사용하여 업데이트의 대기열을 만드는 내부 수정이 있었습니다. 원래 일부 브라우저 엣지 케이스를 수정하기 위한 변경이었는데, 변경 이후 다른 많은 문제를 일으켰습니다. 2.6 버전에서는 원래 이슈를 고칠 수 있는 보다 간단한 방법을 찾았습니다. 이를 통해 nextTick도 모든 케이스에서 Microtasks를 사용하던 예전의 방식대로 되돌렸습니다.

 

기술적인 자세한 내용에 관심이 있다면, 여기에서 확인해주세요.

 

this.$scopedSlots라는 함수는 항상 배열을 반환

(본 변동사항은 렌더 함수 사용자에게만 영향을 미칩니다.) 렌더 함수에서, this.$scopedSlots의 함수들은 범위가 지정된 슬롯을 반환합니다. 지금까지의 버전에서는, 범위가 지정된 슬롯 함수를 호출하면 상위 구성요소가 전달하는 내용을 기반으로 단일 VNode 또는 VNode 배열을 반환할 수 있었습니다. 그로 인해 실은, 리턴값(반환값)을 불분명하게 만들고 의도하지 않은 경우가 발생할 수 있는 실수가 발생하였습니다. Vue 2.6 버전에서는, 범위 지정 슬롯 기능이 VNode 배열 또는 정의되지 않은 상태(undefined)에서도 반환될 수 있게됩니다. 가능한 배열 반환 값을 제대로 확인하지 않으면 기존의 코드 중 일부에 영향을 끼칠 수도 있습니다. 자세한 내용은 여기를 참조하세요.


감사의 말씀

이번 Vue 2.6 버전을 만드는데 기여한 기여자들과 RFC 토의에 참여한 모든 커뮤니티 구성원들에게 감사의 말씀을 전합니다.

 

🖋 원문 출처: Vue 2.6 released medium.com/the-vue-point/vue-2-6-released-66aa6c8e785e

🖋 원문 저자: Evan You

Vue.js의 창조자이자 프로젝트 리더. '나는 코드를 예술작품처럼 디자인하는 것을 꿈꿉니다.'