3.5에서 Vue의 반응성 시스템은 또 다른 주요 리팩터링을 거쳤으며,
더 나은 성능과 크게 향상된 메모리 사용량( -56% )을 달성했지만 동작은 변경되지 않았습니다.
이 리팩터링은 또한 SSR 중에 계산된 값이 중단되어 발생하는 오래된 계산된 값과 메모리 문제를 해결합니다.
또한 3.5에서는 대규모의 반응형 배열에 대한 반응성 추적을 최적화하여
이러한 작업을 어떤 경우에는 최대 10배까지 빠르게 수행할 수 있습니다.
https://blog.vuejs.org/posts/vue-3-5
어떤식으로 메모리 사용량과 빠르게 만들었을까?
PR 세부 정보 확인 해보고 정리해보자!
ARRAY_ITERATE_KEY 도입
ARRAY_ITERATE_KEY는 Vue.js의 반응성 시스템에서 배열 전체에 대한 종속성을 추적하기 위해 도입된 키
기존에는 배열의 각 요소나 인덱스를 개별적으로 추적해야 했지만, 이 키를 사용하면 배열 전체의 변경 사항을 한 번에 감지할 수 있다.
length 속성이나 정수형 인덱스가 변경될 때마다 자동으로 트리거// depsMap은 Map으로, 배열의 각 속성과 인덱스에 대한 종속성을 가집니다.
depsMap = Map {
'length' => Dep (length에 대한 종속성 집합),
0 => Dep (인덱스 0에 대한 종속성 집합),
1 => Dep (인덱스 1에 대한 종속성 집합),
2 => Dep (인덱스 2에 대한 종속성 집합),
// 배열의 크기만큼 인덱스에 대한 종속성이 생성됩니다.
}
// depsMap은 Map으로, 배열의 중요한 속성에 대한 종속성을 가집니다.
depsMap = Map {
'length' => Dep (length에 대한 종속성 집합),
ARRAY_ITERATE_KEY => Dep (배열 전체에 대한 종속성 집합),
// 개별 인덱스에 대한 종속성은 최소화되거나 생략됩니다.
}
기존의 반응성 시스템에서는 배열의 요소와 인덱스에 대한 변경 사항을 개별적으로 추적
메모리 사용량 증가와 성능 저하의 문제 → ARRAY_ITERATE_KEY의 도입으로 배열 전체를 단일 종속성으로 관리
computed 속성의 동작 방식이 개선
computed는 내부적으로 effect를 사용하여 종속성을 추적하고 값을 계산effect가 중지(stopped)되거나 비활성화computed 값이 오래된 상태(stale)로 남아있는 문제가 발생computed는 이제 자체적인 구독자(subscriber) 타입으로 동작하며, 버전 카운팅(version counting)과 이중 연결 리스트(doubly-linked list)를 사용effect에 의존하지 않으므로, 컴포넌트의 언마운트와 관계없이 항상 최신 값을 유지버전 등 새로운 속성을 추가하면 무거워지는 단점이 있지 않을까?
이중 연결 리스트 이전에는? → 종속성 관리를 위해 Set, Map 사용
effect 실행 중에 반응형 데이터에 접근하면, 해당 데이터의 Dep에 effect가 ****구독자로 추가effect는 자신의 종속성 목록에 해당 Dep을 추가effect가 다시 실행되기 전에, 이전에 등록된 모든 종속성을 순회하면서 각 Dep의 구독자 목록에서 effect를 제거이중 연결 리스트 자료구조 적용 후
Dep과 effect가 서로를 양방향으로 연결하여, 종속성 추가 시 참조만 설정전
const props = withDefaults(
defineProps<{
count?: number
msg?: string
}>(),
{
count: 0,
msg: 'hello'
}
)
후
const { count = 0, msg = 'hello' } = defineProps<{
count?: number
message?: string
}>()
<script setup>
import { useId } from 'vue'
const id = useId()
</script>
<template>
<form>
<label :for="id">Name:</label>
<input :id="id" type="text" />
</form>
</template>
APP에 구현된 토스트 컴포넌트 id를 별로 라이브러리로 부여하고 있었는데 이걸 활용할 수 있을 것 같음
<Teleport> 컴포넌트는 마운트될 때 대상 요소가 이미 DOM에 존재해야함<Teleport>보다 나중에 렌더링되는 경우에는 문제defer 속성을 추가하면, <Teleport>는 대상 요소가 존재할 때까지 텔레포트를 지연<Teleport defer target="#container">...</Teleport>
<div id="container"></div>