Vue의 Reactivity와 약간의 React

date
May 16, 2023
slug
reactivity-in-vue-and-react
author
status
Public
tags
summary
type
Post
thumbnail
5.jpg
category
updatedAt
Aug 3, 2025 02:46 PM

Vue의 반응성 시스템 이해하기

Vue의 핵심은 바로반응성(Reactivity)입니다. Vue는 상태(state)의 변화를 감지하고, 이에 따라 DOM을 자동으로 갱신합니다. Vue 2와 Vue 3는 각각 다른 방식으로 반응성을 구현하며, 그 내부 작동 방식은 프레임워크의 성능과 개발 편의성에 큰 영향을 미칩니다.
 

Vue 2: Object.defineProperty 기반 반응성

Vue 2는 ES5의 Object.defineProperty를 활용해 객체의 속성에 대해 getter/setter를 정의하고, 이를 통해 속성의 변경을 감지합니다.
 

기본 개념

const data = { price: 100 }; Object.defineProperty(data, 'price', { get() { console.log('Getting price'); return this._price; }, set(newVal) { console.log('Setting price to', newVal); this._price = newVal; } });
이처럼 Vue는 속성에 접근(get)하거나 값을 변경(set)할 때 자동으로 트래킹하여 UI를 갱신합니다.
 

제한점

  • 신규 속성 추가 감지 불가: data.newProp = 'test'처럼 나중에 추가된 속성은 반응형이 아닙니다.
  • 배열 인덱스 감지 한계: 배열의 인덱스를 직접 변경하거나 length를 수정할 경우 Vue가 변경을 감지하지 못할 수 있습니다.
  • 중첩 객체의 반응성 구현이 복잡: 모든 하위 속성에 일일이 defineProperty를 설정해야 합니다.
 

Vue 3: Proxy 기반 반응성

Vue 3는 ES6의 Proxy API를 이용하여 전체 객체를 감싸는 방식으로 반응성을 구현합니다. 이로 인해 Vue 2에서의 여러 한계를 극복하게 되었습니다.

기본 예시

const target = { message: 'hello' }; const handler = { get(target, prop, receiver) { console.log(`Getting ${prop}`); return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { console.log(`Setting ${prop} to ${value}`); return Reflect.set(target, prop, value, receiver); } }; const proxy = new Proxy(target, handler); console.log(proxy.message); // Getting message proxy.message = 'world'; // Setting message to world
Vue 3 내부에서는 위와 유사한 방식으로 모든 reactive 객체를 감싸고, 속성 접근 및 변경을 추적합니다.

Proxy의 장점

  1. 중첩 객체 자동 반응성: 깊은 중첩 구조도 자동으로 감지.
  1. 배열 지원 향상: 배열 메서드를 재정의하지 않고도 반응성 제공.
  1. 신규 속성 감지: 런타임에서 추가된 속성도 자동으로 반응형 처리.
  1. 성능 개선: 초기 렌더링과 메모리 효율성에서 이점이 있음.
  1. 더 간결한 내부 구현: 프레임워크 유지보수 및 확장성 향상.
❗ 참고: Proxy는 IE11에서는 지원되지 않으므로, Vue 3는 IE11과 호환되지 않습니다.
 

반응성과 기본형(Primitive Values)의 한계

JavaScript의 문자열, 숫자, 불린 값 등 기본형 값은 불변이며, 참조가 아닌 값으로 전달됩니다. Vue는 이러한 기본값을 감지할 수 없습니다.

❌ 반응성 비지원 예시

let count = 1; count = 2; // Vue는 이 변경을 추적할 수 없습니다.

✅ 반응성 유지 예시 (객체로 감싸기)

const state = reactive({ count: 1 }); state.count = 2; // 이 변경은 Vue가 감지합니다.
 

provideinject에서의 반응성 주의사항

Vue의 provide/inject 메커니즘을 사용할 때, 기본형 값을 주입하면 해당 값은 반응형이 아닙니다. 하지만 객체를 주입하면 객체의 속성은 여전히 반응성을 유지합니다.

❌ 기본형 값 주입 시

// 부모 provide('count', 1); // 자식 const count = inject('count'); // 반응성 없음

객체 주입으로 반응성 유지

// 부모 const state = reactive({ count: 1 }); provide('state', state); // 자식 const state = inject('state'); watchEffect(() => { console.log(state.count); // 반응형 추적 가능 });
 

React vs Vue 반응성 비교

항목
Vue 3
React
반응성 도입 방식
Proxy 기반
명시적 상태 관리 (useState 등)
상태 변경 감지
자동 (getter/setter로 추적)
개발자가 직접 setState 호출
중첩 상태 감지
자동으로 추적
수동 처리 필요
의존성 추적
자동
없음 (컴포넌트 전체 리렌더)
최적화 방식
변경된 부분만 리렌더
diff 알고리즘 기반
코드 작성 스타일
Composition API 도입 (유연함)
Hooks 사용 (명시적이고 선언적)
 

⛓ Vue 2 → Vue 3 주요 개선점

Vue 3는 Vue 2의 구조적 한계와 성능 문제를 해결하고자 다음과 같은 개선을 도입했습니다.
  1. 더 강력한 반응성: Proxy 기반 시스템 도입.
  1. Composition API 도입: 코드 재사용성과 모듈화 향상.
  1. Tree Shaking 최적화: 번들 크기 감소.
  1. 멀티 루트 템플릿 지원: <template> 태그 내 여러 루트 엘리먼트 허용.
  1. 가상 DOM 성능 향상: 재작성된 가상 DOM 엔진.
  1. 더 작고 빠른 런타임: 런타임 크기 감소, 로딩 속도 향상.
 

📚 참고 자료