Vue app instance
Vue app instance는 Vue.js framework model 안의 app bootstrapping 개념이자, 컴포넌트 내부에서 데이터를 다루고 생명주기를 관리하는 핵심 단위다. createApp()으로 root component를 Vue runtime에 넘기고 .mount()로 DOM subtree에 연결하는 시작 경계이며,[1] 생성된 인스턴스는 상태(data), 연산(computed/methods), 감시(watchers), 생명주기 훅(lifecycle hooks)이라는 일관된 내부 모델을 가진다.[2] 다만 createApp()을 Vue 전체 모델의 중심으로 과대평가하지는 않는 편이 정확하다 — app instance는 Vue application runtime의 root handle일 뿐이고, 어떤 root component에서 시작해 어떤 DOM subtree를 관리할지 정하는 경계다.
Computed vs Methods: 캐싱이 만드는 차이
App instance의 의미는 단순한 "Vue runtime의 경계 설정"을 넘어, 반응형 상태(Reactive State)와 DOM의 동기화를 관리하는 독립된 런타임 단위로 볼 수 있다.
데이터 기반 연산을 처리할 때 메서드(Methods) 대신 계산된 속성(Computed Properties)을 쓰는 이유는 캐싱(Caching) 때문이다.[2:1] Computed 속성은 종속된 반응형 데이터가 변경될 때만 재평가되며, 그렇지 않으면 이전 캐시된 결과를 즉시 반환해 불필요한 연산을 방지한다. 반면 메서드는 호출될 때마다 다시 실행된다.[2:2] 따라서 같은 계산을 여러 곳에서 반복 호출한다면 일반 Method 대신 computed를 써야 연산 반복을 줄일 수 있다는 것은 이 page의 해석이다. 다만 원문은 computed의 주의점으로 순수 계산 로직만 넣고, 복잡한 로직은 메서드로 분리하며, 무거운 연산을 지양하라고 적는다.[2:3]
Watchers: 부수 효과 경계
Watchers는 상태 변경에 반응하지만 새로운 값을 계산(Computed)하는 데 쓰이기보다는, 비동기 작업이나 비용이 큰 부수 효과(Side Effects)를 수행하는 경계 역할을 한다.[2:4] Watcher 내부에서 단순히 데이터를 가공하려 하면 코드가 복잡해지는데, 이런 계산은 대신 Computed로 옮기는 편이 낫다.
Lifecycle hooks: DOM과의 상호작용 시점
Lifecycle Hooks는 이 인스턴스가 DOM과 어떻게 상호작용하는지 제어하는 시점을 제공한다.[2:5]
created: 인스턴스가 생성되고 반응형 데이터(data, computed 등)가 설정된 직후다. 아직 DOM에 마운트되지 않았으므로 API 호출 등에 적합하다. 이 시점에서 DOM 엘리먼트에 접근하려 하면 아직 렌더링되지 않았기 때문에 실패한다 — DOM 접근은mounted에서 해야 한다.mounted: 인스턴스가 실제 DOM에 연결(mount)된 직후다. DOM 조작이나 외부 라이브러리 연동에 적합하다.updated: 반응형 데이터가 변경되어 가상 DOM이 리렌더링되고 실제 DOM에 패치된 직후다.unmounted: 인스턴스가 마운트 해제되고 해체된 직후다. 이벤트 리스너 해제, 메모리 정리 등에 적합하다.
App instance와 component instance의 경계
App instance는 전체 애플리케이션의 root와 mount boundary를 정하고, component instance는 component tree 안에서 반복적으로 만들어지는 UI 단위다. 하지만 둘 다 본질적으로 동일한 인스턴스 옵션(data, computed, methods, watch, lifecycle hooks)을 공유한다.
mount()는 page 전체를 Vue가 자동 관리한다는 뜻이 아니다. 기본 경계는 mount target 아래 subtree다. Vue app instance는 plugin registration, global app configuration, root component mounting, state management에 쓰인다.
메커니즘
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp({
data() {
return { count: 0 };
},
computed: {
// count가 바뀔 때만 재평가됨 (캐싱)
doubleCount() {
return this.count * 2;
}
},
methods: {
// 호출될 때마다 실행됨
increment() {
this.count++;
}
},
watch: {
// count가 변경될 때 부수 효과 실행
count(newValue, oldValue) {
console.log(`count changed from ${oldValue} to ${newValue}`);
}
},
created() {
console.log("Instance created, reactivity is set up.");
},
mounted() {
console.log("Instance mounted to DOM.");
}
});
app.mount("#app");
flowchart TD
Start["createApp()"] --> Created["created (Reactivity setup)"]
Created --> Mount["mount('#app')"]
Mount --> Mounted["mounted (DOM connected)"]
Mounted -- State changes --> Updated["updated (DOM patched)"]
Mounted -- Unmount called --> Unmounted["unmounted (Cleanup)"]관련
- Vue.js: app instance는 Vue framework model의 bootstrapping 단계다.
- Vue reactivity: mount 이후 state change가 DOM update로 이어지는 메커니즘이며, computed와 watchers의 근간이 된다.
- Browser DOM and Script Loading:
created에서 DOM 접근이 실패하는 것은 head의 script가 아직 생성되지 않은 노드에 접근하는 문제와 같은 구조로 읽을 수 있다. - JavaScript Asynchronous Execution: watcher가 맡는 비동기 작업이 실제로 어떤 흐름(Promise, async/await)으로 실행되는지 설명한다.
출처
테스트 질문
- 메서드(Methods) 대신 계산된 속성(Computed Properties)을 사용하는 주된 이유는 무엇인가?
- Vue 인스턴스의 Lifecycle Hook 중
created와mounted단계에서 일어나는 핵심적인 차이는 무엇인가? - App instance와 component instance는 어떻게 다르며, 어떤 속성들을 공유하는가?
01-1.Vuejs-intro.pdf — Vue app을
createApp()으로 생성하고.mount()로 DOM element에 연결한다는 소개 ↩︎02.Vuejs-instance.pdf —
data/methods/computed/watch속성,created/mounted/updated/unmountedlifecycle hook 설명; computed(p.10): "method는 호출 회수만큼 동작하지만 computed는 호출 회수와 상관없이 한번만 동작한 후 caching해서 사용", 주의점 "순수 계산 로직만 포함 ::> 복잡한 로직의 경우 메서드로 분리", "무거운 연산 지양"; 캐싱 메커니즘(p.11): "이는 불필요한 연산을 줄여 성능을 향상시키는 중요한 기능임" ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎