1. 서론
Vue 2와는 달리 Vue 3에서는 Composition API를 쓰므로 전부 함수 형태의 훅(hook)으로 바뀝니다.
- created -> 따로 없음(대부분 setup 안에서 처리)
- mounted -> onMounted
- beforeUnmount, unmounted -> onBeforeUnmount, onUnmounted
- updated -> onUpdated 등
Vue 3 공식 문서에서는 이들을 생명주기 훅(Lifecycle Hooks)이라고 부르고,
Composition API 안에서 직접 import 해서 사용하는 패턴으로 설명합니다.
이번 글에서는
- Vue 2 라이프사이클과 Vue 3 Composition 라이프사이클의 대응 관계
- onMounted, onUnmounted를 중심으로 한 기본 사용 패턴
- 이벤트/타이머 등록 및 해제 예제
까지 한 번에 정리해볼게요.
2. Vue 2와 Vue 3 라이프사이클 훅 대응표
| Vue 2 (Options API) | Vue 3 (Composition API) |
| beforeCreate | 거의 사용 X, setup으로 대체 |
| created | setup() 내부 코드 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| destroyed | onUnmounted |
Vue 3에서도 Options API를 그대로 쓸 수 있지만,
Composition API를 쓰는 순간부터는 위 오른쪽 컬럼의 함수들을 쓰게 된다고 보면 됩니다.
3. onMounted
호출 시점은 언제일까?
onMounted는 컴포넌트의 템플릿이 실제 DOM에 마운트된 직후에 호출됩니다.
Vue 2의 mounted와 동일한 타이밍입니다.
사용법은 아래와 같습니다.
<script>
import { ref, onMounted } from 'vue'
export default {
setup() {
const message = ref('')
onMounted(() => {
console.log('컴포넌트가 화면에 마운트되었습니다.')
message.value = '마운트 이후에 설정한 텍스트'
})
return { message }
}
}
</script>
<template>
<p>{{ message }}</p>
</template>
onMounted는 Vue가 import 해주는 함수이고
setup 안에서만 호출해야 합니다. (컴포넌트 생성 과정에서 한 번만 동작)
언제 onMounted를 써야 할까?
- DOM에 직접 접근해야 할 때 (ref로 엘리먼트 잡고 크기 측정 등)
- 초기에 한 번만 필요한 side effect (로그 출력, 스크롤 위치 조정 등)
- "화면에 그려진 뒤" 서버에 알리는 이벤트 등
단, 단순한 데이터 초기화는 굳이 onMounted가 아니라 setup 안에서 바로 해도 됩니다.
DOM이 실제로 붙어 있어야만 하는 작업인지를 기준으로 나누면 헷갈리지 않아요.
즉, onMounted는 DOM이 붙은 뒤에 하고 싶은 일을 적는 곳입니다.
4. onUnmounted
Vue 2에서 destroyed에서 하던 일을 Vue 3에서는 보통 onUnmounted에 넣습니다.
이 훅은 컴포넌트가 화면에서 제거된 직후 호출됩니다.
대표적인 용도는 아래와 같습니다.
- setInterval, setTimeout 정리
- window / document에 등록한 이벤트 리스너 제거
- 외부 라이브러리 인스턴스 해제 (chart, map 등)
<script>
import { ref, onMounted, onUnmounted } from 'vue'
export default {
setup() {
const width = ref(window.innerWidth)
function updateWidth() {
width.value = window.innerWidth
}
onMounted(() => {
window.addEventListener('resize', updateWidth)
})
onUnmounted(() => {
window.removeEventListener('resize', updateWidth)
})
return { width }
}
}
</script>
<template>
<p>현재 창 가로 길이: {{ width }}</p>
</template>
이 예제는 마운트 시 이벤트 등록 -> 언마운트 시 이벤트 해제 구조를 나타낸 것입니다.
5. onBeforeMount / onBeforeUnmount / onUpdated
실무에서는 대부분 onMounted, onUnmounted 만으로도 충분하지만,
상황에 따라 이 셋이 유용할 수 있습니다.
onBeforeMount
- 템플릿이 실제 DOM에 붙기 직전에 호출
- DOM은 아직 접근할 수 없는 시점이라, 보통 특별한 일이 없으면 잘 쓰지 않습니다.
import { onBeforeMount } from 'vue'
onBeforeMount(() => {
console.log('곧 마운트될 예정')
})
onUpdated
- 반응형 상태가 바뀌고, 그에 따라 DOM 업데이트까지 끝난 뒤 호출
- 특정 상태 변화 후 DOM을 한 번 더 읽어야 할 때, 혹은 디버깅으로 "언제 화면이 갱신되는지" 확인할 때 좋습니다.
import { ref, onUpdated } from 'vue'
const count = ref(0)
onUpdated(() => {
console.log('DOM 업데이트 완료, 현재 count:', count.value)
})
onBeforeUnmount
- 컴포넌트가 화면에서 제거되기 직전 호출
- 로그를 남기거나, 사용자에게 "정말 나갈까요?" 같은 확인 절차를 두는 등 언마운트 전에 한 번 걸러야 하는 작업에 쓰입니다.
import { onBeforeUnmount } from 'vue'
onBeforeUnmount(() => {
console.log('곧 컴포넌트가 언마운트 됩니다.')
})
6. 예제
지금까지 본 것들을 타이머 + 창 크기 추적하는 예제에 녹여보겠습니다.
<script>
import { ref, onMounted, onUnmounted } from 'vue'
export default {
setup() {
const seconds = ref(0)
const width = ref(window.innerWidth)
let timerId = null
function updateWidth() {
width.value = window.innerWidth
}
onMounted(() => {
// 1초마다 seconds 증가
timerId = setInterval(() => {
seconds.value++
}, 1000)
// 창 크기 변경 이벤트 등록
window.addEventListener('resize', updateWidth)
})
onUnmounted(() => {
// 타이머 정리
if (timerId) {
clearInterval(timerId)
}
// 이벤트 리스너 제거
window.removeEventListener('resize', updateWidth)
})
return {
seconds,
width
}
}
}
</script>
<template>
<div>
<p>컴포넌트가 화면에 떠 있는 시간: {{ seconds }}</p>
<p>현재 창 가로 길이: {{ width }}px</p>
</div>
</template>
이 패턴만 자연스럽게 쓸 수 있으면
마운트 시에만 해야 하는 일, 언마운트 시 꼭 정리해야 하는 일을
Composition API 기준으로 무리 없이 처리할 수 있습니다.
정리
- Vue 2 라이프사이클 -> Vue 3 Composition API 매핑
- created -> setup() 안
- mounted -> onMounted
- destroyed -> onUnmounted
- onMounted
- DOM이 실제로 붙은 뒤 실행
- DOM 접근, 초기 API 호출, 외부 라이브러리 초기화 등에 사용
- onUnmounted
- 컴포넌트가 제거된 직후 실행
- 이벤트 리스너, 타이머, 외부 인스턴스 정리에 필수
- 나머지 훅들
- onBeforeMount, onBeforeUnmount, onUpdated 등은 필요할 때만 골라 쓰면 됨
이제 다음 단계에서 onMounted랑 watch, watchEffect, computed 등과 섞어서 쓰기 시작하면 실전 컴포넌트 로직을 거의 다 커버할 수 있는 수준까지 올라가게 됩니다.
출처
Vue 3 마이그레이션 공식 문서 - Render Function API
'Framework > Vue' 카테고리의 다른 글
| Vue 2 vs Vue 3 비교: Options API에서 Composition API로 마이그레이션 (0) | 2025.11.25 |
|---|---|
| Vue 3 Composable 패턴 이해하기: userCounter, useFetch로 로직 재사용하기 (0) | 2025.11.24 |
| Vue3 Composition API: setup, ref, reactive로 상태 관리 (0) | 2025.11.24 |
| Vue3 입문: Vite로 프로젝트 생성하고 createApp 큰 그림 잡기 (0) | 2025.11.24 |
| Vue CLI로 Vue 프로젝트 만들기 (0) | 2025.11.21 |