Vue의 핵심은 바로반응성(Reactivity)입니다. Vue는 상태(state)의 변화를 감지하고, 이에 따라 DOM을 자동으로 갱신합니다. Vue 2와 Vue 3는 각각 다른 방식으로 반응성을 구현하며, 그 내부 작동 방식은 프레임워크의 성능과 개발 편의성에 큰 영향을 미칩니다.
Object.defineProperty 기반 반응성Vue 2는 ES5의 Object.defineProperty를 활용해 객체의 속성에 대해 getter/setter를 정의하고, 이를 통해 속성의 변경을 감지합니다.
1const data = { price: 100 };
2
3Object.defineProperty(data, 'price', {
4 get() {
5 console.log('Getting price');
6 return this._price;
7 },
8 set(newVal) {
9 console.log('Setting price to', newVal);
10 this._price = newVal;
11 }
12});이처럼 Vue는 속성에 접근(get)하거나 값을 변경(set)할 때 자동으로 트래킹하여 UI를 갱신합니다.
data.newProp = 'test'처럼 나중에 추가된 속성은 반응형이 아닙니다.length를 수정할 경우 Vue가 변경을 감지하지 못할 수 있습니다.defineProperty를 설정해야 합니다.Proxy 기반 반응성Vue 3는 ES6의 Proxy API를 이용하여 전체 객체를 감싸는 방식으로 반응성을 구현합니다. 이로 인해 Vue 2에서의 여러 한계를 극복하게 되었습니다.
1const target = { message: 'hello' };
2
3const handler = {
4 get(target, prop, receiver) {
5 console.log(`Getting ${prop}`);
6 return Reflect.get(target, prop, receiver);
7 },
8 set(target, prop, value, receiver) {
9 console.log(`Setting ${prop} to ${value}`);
10 return Reflect.set(target, prop, value, receiver);
11 }
12};
13
14const proxy = new Proxy(target, handler);
15
16console.log(proxy.message); // Getting message
17proxy.message = 'world'; // Setting message to world
18
19Vue 3 내부에서는 위와 유사한 방식으로 모든 reactive 객체를 감싸고, 속성 접근 및 변경을 추적합니다.
❗ 참고: Proxy는 IE11에서는 지원되지 않으므로, Vue 3는 IE11과 호환되지 않습니다.
JavaScript의 문자열, 숫자, 불린 값 등 기본형 값은 불변이며, 참조가 아닌 값으로 전달됩니다. Vue는 이러한 기본값을 감지할 수 없습니다.
let count = 1;
count = 2; // Vue는 이 변경을 추적할 수 없습니다.const state = reactive({ count: 1 });
state.count = 2; // 이 변경은 Vue가 감지합니다.provide와 inject에서의 반응성 주의사항Vue의 provide/inject 메커니즘을 사용할 때, 기본형 값을 주입하면 해당 값은 반응형이 아닙니다. 하지만 객체를 주입하면 객체의 속성은 여전히 반응성을 유지합니다.
// 부모
provide('count', 1);
// 자식
const count = inject('count'); // 반응성 없음1// 부모
2const state = reactive({ count: 1 });
3provide('state', state);
4
5// 자식
6const state = inject('state');
7watchEffect(() => {
8 console.log(state.count); // 반응형 추적 가능
9});| 항목 | Vue 3 | React |
|---|---|---|
| 반응성 도입 방식 | Proxy 기반 | 명시적 상태 관리 (useState 등) |
| 상태 변경 감지 | 자동 (getter/setter로 추적) | 개발자가 직접 setState 호출 |
| 중첩 상태 감지 | 자동으로 추적 | 수동 처리 필요 |
| 의존성 추적 | 자동 | 없음 (컴포넌트 전체 리렌더) |
| 최적화 방식 | 변경된 부분만 리렌더 | diff 알고리즘 기반 |
| 코드 작성 스타일 | Composition API 도입 (유연함) | Hooks 사용 (명시적이고 선언적) |
Vue 3는 Vue 2의 구조적 한계와 성능 문제를 해결하고자 다음과 같은 개선을 도입했습니다.
Proxy 기반 시스템 도입.<template> 태그 내 여러 루트 엘리먼트 허용.