[Vue] Vue.js 라이프사이클 이해하기
#목차
- Vue Lifecycle 이란?
- Vue Instance 란?
- Composition API 란?
- Vue 2 코드를 Vue 3 Lifecycle Hooks로 업데이트된 항목
- Vue Lifecycle Hooks
- Creation Hooks
- Mounting Hooks
- Update Hooks
- Destruction Hooks – Cleaning Things Up
- Activation Hooks – Managing Keep-Alive Components
- Vue 3 Debug Hooks
- 결론!
Vue Lifecycle 이란?
“각 Vue 구성 요소 Instance는 생성될 때 일련의 초기화 단계를 거치게 된다. 예를 들어, 데이터 관찰(Create)을 설정하고 템플릿을 컴파일하고 DOM에 인스턴스를 마운트(Mount)하고 데이터가 변경될 때 DOM을 업데이트(Update)해야 한다. 그 과정에서 Lifecycle Hooks 이라는 기능도 실행하여 사용자가 특정 단계에서 자신의 코드를 추가할 수 있는 기회를 제공한다.” - Vue Lifecycle
Vue Instance 란?
“Instance란 모든 Vue.js 앱은 Vue를 사용하여 루트 Vue 인스턴스를 생성하여 부트스트랩된다.” - Vue Instance
즉, Instance는 Vue.js로 화면을 개발하기 위해 꼭 생성해야 하는 필수 단위.
new Vue({...})
로 선언하여 만들어진 객체를 Vue 인스턴스라고 부른다.
<script>
new Vue({ // instance 생성
// instance option properties
});
</script>
Composition API 란?
“컴포지션(Composition) API는 컴포넌트 내에서 사용하는 특정 기능을 갖는 코드를 유연하게 구성하여 사용할 수 있도록 Vue3 버전에 추가된 함수 기반의 API이다. 컴포넌트 API가 생긴 이유는 Vue는 프로젝트 규모가 커질수록 관리하기 힘든 단점과 컴포넌트의 계층구조가 복잡할수록 코드에 대한 추적 및 관리가 힘든 점을 보안하기 위해 등장하게 되었다.” - Composition API
beforeCreate
및 created
(setup()
메서드 자체로 대체됨)를 제외하고 설정 메소드에서 액세스할 수 있는 옵션 API lifecycle hooks 중 9개가 있다.
onBeforeMount
: mounting이 시작되기 전에 호출onMounted
: 컴포넌트가 mount될 때 호출onBeforeUpdate
: 반응형 데이터가 변경될 때와 re-render되기 전에 호출onUpdated
: re-render된 후에 호출onBeforeUnmount
: Vue 인스턴스가 파괴(삭제)되기 전에 호출onUnmounted
: 인스턴스가 파괴(삭제)된 후 호출됨onActivated
: 보관된 구성 요소가 활성화되면 호출onDeactivated
: 보관된 구성 요소가 비활성화되면 호출onErrorCaptured
: 하위 구성 요소에서 오류가 캡처되면 호출
Vue 2 코드를 Vue 3 Lifecycle Hooks로 업데이트된 항목
- beforeCreate -> use setup()
- created -> use setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
Vue Lifecycle Hooks
Creation Hooks
“Composition API를 사용하는 Vue 3 Lifecycle Hooks의 경우
beforeCreate
와created
모두setup()
메서드로 대체된다.” - Creation Hooks
import { ref } from 'vue';
export default {
setup() {
const val = ref('hello');
console.log('Value of val is: ' + val.value); // Value of val is: hello
return {
val,
}
},
}
Mounting Hooks
“Mounting Hooks는
Component Mounting
및Rendering
을 처리한다.” - Mounting Hooks
beforeMount()
와 onBeforeMount()
“컴포넌트 DOM이 실제로 렌더링되고 마운트되기 직전에 호출된다. 이 단계에서는
Root Element
가 아직 존재하지 않는다. Options API에서this.$el
을 사용하여 액세스할 수 있고, Composition API에선ref
를 사용해야 한다.” - onBeforeMount()
Options API
export default {
beforeMount() {
console.log(this.$el); // null
},
}
Composition API
<template>
<div ref="root">Hello World</div>
</template>
<script>
import { ref, onBeforeMount } from 'vue';
export default {
setup() {
const root = ref(null);
/* Composition API */
onBeforeMount(() => {
console.log(root.value); // null
})
return {
root,
}
},
beforeMount() {
/* Options API */
console.log(this.$el); // null
},
}
</script>
mount()
와 onMount()
“Component의 첫 번째 렌더링 직후에 호출된다. 이 단계에서는 직접 DOM 액세스를 허용하는 요소를 사용할 수 있다. Options API에서는
$el
을 사용하여 DOM에 액세스하고, Composition API에서 Vue 라이프사이클 훅의 DOM에 액세스하려면ref
를 사용해야 한다.” - onMount()
import { ref, onMounted } from 'vue';
export default {
setup() {
/* Composition API */
const root = ref(null)
onMounted(() => {
console.log(root.value); // null
})
return {
root,
}
},
mounted() {
/* Options API */
console.log(this.$el); // <div ...>
},
}
Update Hooks
“업데이트된 Lifecycle event는 반응형 데이터(Reactive Data)가 수정될 때마다 트리거되어 렌더 업데이트를 트리거된다.” - Update Hooks
beforeUpdate()
와 onBeforeUpdate()
“데이터가 변경될 때 Component가 다시 렌더링되기 전에 실행된다. 변경 사항이 발생하기 전에 DOM을 수동으로 업데이트하기에 좋은 곳이다.” - onBeforeUpdate()
update()
와 onUpdate()
“DOM이 업데이트되면 업데이트된 메서드가 호출하게 된다.” - onUpdate()
<template>
<div>
<p> | edited 8 times</p>
<button @click="val = Math.random(0, 100)">Click to Change</button>
</div>
</template>
Options API
<script>
export default {
data() {
return {
val: 0,
}
},
beforeUpdate() {
console.log('beforeUpdate() val: ' + this.val); // beforeUpdate() val: 0.random value
},
updated() {
console.log('updated() val: ' + this.val); // updated() val: 0. change random value
},
}
</script>
Composition API
<script>
import { ref, onBeforeUpdate, onUpdated } from 'vue';
export default {
setup() {
const count = ref(0);
const val = ref(0);
onBeforeUpdate(() => {
count.value++
console.log('beforeUpdate'); // beforeUpdate
})
onUpdated(() => {
console.log('updated() val: ' + val.value); // updated() val: 0.random value
})
return {
count,
val,
}
},
}
</script>
Destruction Hooks – Cleaning Things Up
“Destruction Hooks는 Component를 제거하고, 허술하게 남은 것들을 모두 치우는 과정에서 사용된다. 제대로 처리되지 않으면 메모리 누수를 유발할 수 있는 이벤트 리스너와 항목을 제거하게 된다.” - Destruction Hooks
beforeUnmounted()
와 onBeforeUnmounted()
“해당 단계는 Component가 분해되기 전이기 때문에, 전부는 아니더라도 대부분의 정리 작업을 수행해야 할 때이다. 이 단계에서 구성 요소는 여전히 완전히 작동하며 아직 손상된 것은 없다.” - onBeforeUnmounted()
Options API
export default {
mounted() {
console.log('mount'); // mount
window.addEventListener('resize', this.someMethod);
},
beforeUnmount() {
console.log('unmount');
window.removeEventListener('resize', this.someMethod);
},
methods: {
someMethod() {
// do something
},
},
}
Composition API
import { onMounted, onBeforeUnmount } from 'vue';
export default {
setup() {
const someMethod = () => {
// do smth
}
onMounted(() => {
console.log('mount'); // mount
window.addEventListener('resize', someMethod);
})
onBeforeUnmount(() => {
console.log('unmount');
window.removeEventListener('resize', someMethod);
})
},
}
- 코드가 업데이트되면 일부 구성 요소가 자체적으로 마운트 해제 및 마운트가 된다.
unmounted()
와 onUnmounted()
“이 시점에서 대부분의 구성 요소와 구성 요소의 속성이 사라지므로 수행할 수 있는 작업이 많지 않다. 다시 한 번, 일부 데이터를 스캔하여 정확히 무엇이 남아 있는지, 프로젝트에 유용할 수 있는지 확인하는 단계이다.” - onBeforeUnmounted()
import { onUnmounted } from 'vue';
export default {
setup() {
/* Composition API */
onUnmounted(() => {
console.log('unmounted');
})
},
unmounted() {
/* Options API */
console.log('unmounted');
},
}
Activation Hooks – Managing Keep-Alive Components
“
<keep-alive>
태그는 동적 Component의wrapper element
이다. 동적 Component가 변경될 때마다 Vue가 완전히 새로운 인스턴스를 생성할 필요가 없도록 비활성 구성 요소에 대한 캐시된 참조를 저장하게 된다.” - Activation Hooks
activated()
와 onActivated()
“이 메서드는 활성 상태로 유지된 동적 구성 요소가
"활성화"
될 때마다 호출됩니다. 즉, 동적 Component의 active view가 됩니다.” - onActivated()
<template>
<div>
<span @click="tabName = 'Tab1'">Tab 1 </span>
<span @click="tabName = 'Tab2'">Tab 2</span>
<keep-alive>
<component :is="tabName" class="tab-area" />
</keep-alive>
</div>
</template>
<script>
import Tab1 from './Tab1.vue';
import Tab2 from './Tab2.vue';
import { ref } from 'vue'
export default {
components: {
Tab1,
Tab2,
},
setup() {
/* Composition API */
const tabName = ref('Tab1');
return {
tabName,
}
},
}
</script>
Tab1.vue
Component 내에서 활성화 후크에 다음과 같이 액세스할 수 있다.
<template>
<div>
<h2>Tab 1</h2>
<input type="text" placeholder="this content will persist!" />
</div>
</template>
<script>
import { onActivated } from 'vue';
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated');
})
},
}
</script>
deactivated()
와 onDeactivated()
“활성 상태 유지 Component가 더 이상 동적 구성 요소의 active view가 아닐 때 호출된다. 이 Hooks는 특정 뷰가 포커스를 잃고 애니메이션을 트리거할 때 사용자 데이터를 저장하는 것과 같은 사용 사례에 유용할 수 있다.” - onDeactivated()
import { onActivated, onDeactivated } from 'vue';
export default {
setup() {
onActivated(() => {
console.log('Tab 1 Activated');
})
onDeactivated(() => {
console.log('Tab 1 Deactivated');
})
},
}
- 이제 탭을 전환하면 각 동적 구성 요소의 상태가 캐시되고 저장된다.
Vue 3 Debug Hooks
“Vue 3은 디버깅 목적으로 사용할 수 있는 두 개의 후크를 제공한다.” - Debug Hooks
onRenderTracked
onRenderTriggered
이 두 이벤트 모두 Vue 인스턴스에서 다시 렌더링을 일으키는 원인을 알려주는DebuggerEvent
를 사용한다.
export default {
onRenderTriggered(e) {
debugger
// inspect which dependency is causing the component to re-render
},
}
결론!
- Vue 인스턴스는 크게
생성(create)
되고,DOM에 부착(mount)
되고,업데이트(update)
되며,없어지는(destroy)
4가지 과정을 거치게 된다. - 이 과정에서 Vue는 각각의 단계에서, Vue를 사용하는 사람들을 위해 훅(Hook)을 할 수 있도록 API를 제공하게 된다. 일반적으로 많이 사용하는 종류로는
beforeCreate
및created
(setup()
메서드 자체로 대체됨),beforeMount
,mounted
,beforeUpdate
,updated
,beforeDestroy
,destroyed
가 있다.
Back to [Vue] Vue.js 란?