Vue의 컴포넌트는 단순히 화면에 나타나기만 하는 것이 아니라, 생성되고 화면에 붙고, 데이터 변화에 따라 갱신되고, 마지막에는 화면에서 제거되는 과정을 거친다.
이 전체 과정을 Component Lifecycle이라고 한다.
쉽게 정리하면 다음과 같다.
생성
↓
마운트
↓
업데이트
↓
언마운트
그리고 Vue는 각 단계마다 특정 시점에 원하는 코드를 실행할 수 있도록 Lifecycle Hook을 제공한다.
대표적으로 다음과 같은 함수들이 있다.
onMounted()
onUpdated()
onUnmounted()
즉, Lifecycle은 컴포넌트의 전체 생명주기이고, Lifecycle Hook은 그 생명주기의 특정 시점에 실행되는 함수라고 보면 된다.
Component Lifecycle이란?
컴포넌트는 화면에 등장하기 전부터 내부적으로 여러 단계를 거친다.
예를 들어 다음과 같은 Vue 컴포넌트가 있다고 해보자.
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">
{{ count }}
</button>
</template>
이 컴포넌트가 실행되면 내부적으로 다음과 같은 흐름을 거친다.
컴포넌트 생성
↓
반응형 데이터 준비
↓
DOM에 연결
↓
화면 표시
↓
count 변경
↓
화면 업데이트
↓
컴포넌트 제거
이처럼 컴포넌트는 한 번 만들어지고 끝나는 것이 아니라 여러 상태를 거쳐 움직인다.
Vue에서는 이 과정을 크게 다음 네 단계로 나눌 수 있다.
Creation
Mounting
Updating
Unmounting
생성 단계 Creation
생성 단계는 컴포넌트가 메모리상에 만들어지는 시점이다.
이 단계에서는 <script setup> 내부의 코드가 실행되고, ref, reactive, computed, watch 같은 반응형 데이터와 로직이 준비된다.
예를 들어 다음과 같다.
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log('컴포넌트 생성')
</script>
이 시점에는 컴포넌트가 아직 실제 브라우저 DOM에 완전히 붙기 전이다.
따라서 화면 요소에 직접 접근하는 작업은 아직 적절하지 않다.
생성 단계는 주로 다음과 같이 이해하면 된다.
컴포넌트 메모리 생성
↓
반응형 상태 초기화
↓
함수와 계산 로직 준비
마운트 단계 Mounting
마운트는 컴포넌트가 실제 브라우저 DOM에 연결되는 단계다.
즉, <template>에 작성한 div, button, input 같은 요소가 실제 화면에 만들어진 상태다.
이 시점에 사용하는 대표적인 Lifecycle Hook이 onMounted()다.
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
console.log('컴포넌트가 DOM에 연결됨')
})
</script>
onMounted()는 컴포넌트가 실제 화면에 붙은 뒤 실행된다.
흐름을 보면 다음과 같다.
컴포넌트 생성
↓
Virtual DOM 구성
↓
Real DOM에 연결
↓
onMounted()
이 시점에는 실제 DOM 요소가 존재하므로 DOM 접근이 가능하다.
또한 초기 데이터를 가져오는 작업도 이 단계에서 처리할 수 있다.
예를 들어 서버에서 사용자 목록을 가져온다고 해보자.
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const users = ref([])
onMounted(async () => {
const response = await axios.get('/api/users')
users.value = response.data
})
</script>
전체 흐름은 다음과 같다.
컴포넌트 생성
↓
DOM에 연결
↓
onMounted()
↓
API 요청
↓
데이터 저장
↓
화면 갱신
업데이트 단계 Updating
Vue에서 ref나 reactive 같은 반응형 데이터가 변경되면 화면도 함께 변경된다.
예를 들어 다음과 같은 코드가 있다고 해보자.
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">
{{ count }}
</button>
</template>
버튼을 누르면 count 값이 변경된다.
count = 0
↓
버튼 클릭
↓
count = 1
Vue는 이 변화를 감지하고 화면을 다시 갱신한다.
반응형 데이터 변경
↓
Vue가 변경 감지
↓
Virtual DOM 갱신
↓
변경된 부분 확인
↓
Real DOM 반영
업데이트가 완료된 이후 실행되는 Hook이 onUpdated()다.
<script setup>
import { onUpdated } from 'vue'
onUpdated(() => {
console.log('화면 업데이트 완료')
})
</script>
따라서 데이터 변경 이후 DOM 상태를 확인해야 하는 경우 사용할 수 있다.
다만 onUpdated()는 컴포넌트가 업데이트될 때마다 실행될 수 있기 때문에 무거운 작업을 넣는 것은 피하는 것이 좋다.
예를 들어 onUpdated() 내부에서 또 다른 반응형 데이터를 계속 변경하면 반복적인 업데이트가 발생할 수 있다.
언마운트 단계 Unmounting
언마운트는 컴포넌트가 화면에서 제거되는 단계다.
예를 들어 다음과 같은 부모 컴포넌트가 있다고 해보자.
<ChildComponent v-if="isVisible" />
isVisible이 false가 되면 ChildComponent는 화면에서 제거된다.
isVisible = true
↓
ChildComponent 존재
isVisible = false
↓
ChildComponent 제거
이 시점에 사용하는 대표적인 Hook이 onUnmounted()다.
<script setup>
import { onUnmounted } from 'vue'
onUnmounted(() => {
console.log('컴포넌트 제거 완료')
})
</script>
언마운트 단계에서 중요한 것은 Cleanup 작업이다.
왜 Cleanup이 필요할까?
컴포넌트가 사라졌다고 해서 모든 JavaScript 작업이 자동으로 종료되는 것은 아니다.
예를 들어 컴포넌트에서 타이머를 실행했다고 해보자.
const timerId = setInterval(() => {
console.log('실행 중')
}, 1000)
컴포넌트가 화면에서 제거되어도 setInterval()은 계속 실행될 수 있다.
이를 그대로 두면 불필요한 연산이 계속 발생하고 메모리 누수의 원인이 될 수 있다.
그래서 컴포넌트가 제거될 때 타이머도 함께 정리한다.
<script setup>
import { onMounted, onUnmounted } from 'vue'
let timerId
onMounted(() => {
timerId = setInterval(() => {
console.log('실행 중')
}, 1000)
})
onUnmounted(() => {
clearInterval(timerId)
})
</script>
전체 흐름은 다음과 같다.
컴포넌트 생성
↓
onMounted()
↓
setInterval 시작
↓
컴포넌트 사용
↓
컴포넌트 제거
↓
onUnmounted()
↓
clearInterval()
타이머뿐만 아니라 전역 이벤트 리스너 같은 작업도 같은 방식으로 정리할 수 있다.
Before Hook도 있다
Vue에는 각 주요 단계가 실행되기 직전 시점을 다룰 수 있는 Hook도 있다.
대표적으로 다음과 같다.
onBeforeMount()
onBeforeUpdate()
onBeforeUnmount()
전체 흐름을 보면 이해하기 쉽다.
컴포넌트 생성
↓
onBeforeMount()
↓
DOM에 연결
↓
onMounted()
↓
데이터 변경
↓
onBeforeUpdate()
↓
DOM 업데이트
↓
onUpdated()
↓
컴포넌트 제거 시작
↓
onBeforeUnmount()
↓
DOM에서 제거
↓
onUnmounted()
주요 Lifecycle Hook 정리
| Lifecycle Hook | 실행 시점 | 주요 용도 |
| onBeforeMount() | DOM에 연결되기 직전 | 마운트 전 처리 |
| onMounted() | DOM에 연결된 후 | API 호출, DOM 접근 |
| onBeforeUpdate() | DOM 업데이트 직전 | 업데이트 전 상태 확인 |
| onUpdated() | DOM 업데이트 완료 후 | 변경된 DOM 처리 |
| onBeforeUnmount() | 컴포넌트 제거 직전 | 제거 전 정리 |
| onUnmounted() | 컴포넌트 제거 후 | 타이머, 이벤트 정리 |
처음에는 다음 세 가지를 중심으로 이해하면 된다.
onMounted()
→ 컴포넌트가 화면에 붙은 뒤
onUpdated()
→ 화면이 업데이트된 뒤
onUnmounted()
→ 컴포넌트가 제거된 뒤
onMounted와 API 호출
Lifecycle Hook 중 onMounted()는 초기 데이터 조회와 연결되는 경우가 많다.
예를 들어 날씨 데이터를 가져오는 컴포넌트를 만든다고 해보자.
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const weather = ref(null)
onMounted(async () => {
const response = await axios.get('/api/weather')
weather.value = response.data
})
</script>
<template>
<div v-if="weather">
{{ weather.temperature }}
</div>
</template>
흐름은 다음과 같다.
Weather Component 생성
↓
DOM Mount
↓
onMounted()
↓
Backend API 호출
↓
JSON 응답
↓
weather 변경
↓
화면 업데이트
이 구조는 Lifecycle과 Vue의 반응형 데이터가 어떻게 연결되는지를 보여준다.
전체 Lifecycle 흐름
Component Lifecycle 전체를 하나로 정리하면 다음과 같다.
Component 생성
↓
<script setup>
↓
onBeforeMount()
↓
DOM Mount
↓
onMounted()
↓
┌─────────────┐
│ │
│ 데이터 변경 │
│ │
└──────┬──────┘
↓
onBeforeUpdate()
↓
DOM Update
↓
onUpdated()
↓
데이터가 변경되면
위 과정 반복
↓
onBeforeUnmount()
↓
DOM에서 제거
↓
onUnmounted()
즉 컴포넌트는 단순히 한 번 렌더링되는 것이 아니라, 상태 변화에 따라 여러 번 업데이트되다가 필요 없어지면 제거된다.
정리
Component Lifecycle은 Vue 컴포넌트가 생성되고 제거될 때까지 거치는 전체 과정이다.
크게 네 단계로 구분할 수 있다.
Creation
↓
Mounting
↓
Updating
↓
Unmounting
그리고 Vue는 각 단계에 맞춰 코드를 실행할 수 있도록 Lifecycle Hook을 제공한다.
Mount
→ onMounted()
Update
→ onUpdated()
Unmount
→ onUnmounted()
실제로 중요한 흐름은 다음과 같다.
컴포넌트 생성
↓
화면에 연결
↓
초기 데이터 요청
↓
사용자의 입력
↓
반응형 데이터 변경
↓
화면 업데이트
↓
컴포넌트 제거
↓
타이머 / 이벤트 정리
한 문장으로 정리하면 다음과 같다.
Component Lifecycle은 Vue 컴포넌트가 생성, 마운트, 업데이트, 언마운트되는 전체 생명주기이며, Lifecycle Hook은 각 시점에 원하는 로직을 실행할 수 있도록 제공되는 함수다.
'개발 > JavaScript' 카테고리의 다른 글
| [JavaScript][Vue.js] provide / inject 정리 - 깊은 컴포넌트 간 데이터 전달 (0) | 2026.08.26 |
|---|---|
| [JavaScript][Vue.js] Props와 Emits 정리 - 부모·자식 컴포넌트 통신 (0) | 2026.08.26 |
| [JavaScript][Vue.js] Composition API란? - Options API와의 차이부터 ref, computed, watch까지 (0) | 2026.08.26 |
| [JavaScript][Vue.js] Vue Directive 문법 정리 - v-bind부터 v-if, v-for까지 (1) | 2026.08.24 |
| [JavaScript][Vue.js] Vue 기본 개념 이해하기 (0) | 2026.08.24 |