Vue.js 라이프사이클: Composition API 훅으로 보는 컴포넌트의 일생
한눈에 보기
Vue 컴포넌트가 생성, 마운트, 갱신, 소멸하는 라이프사이클 전 과정을 다룬다. Composition API 훅의 시점별 역할과 Options API 대응 관계, 데이터 요청과 자원 정리를 배치하는 올바른 시점을 정리한다.
최종 업데이트 2026.09.17
Vue.js(뷰) 라이프사이클은 컴포넌트가 생성되어 DOM에 연결되고, 데이터 변화에 따라 갱신되다가, 화면에서 제거되기까지의 전체 과정을 뜻한다. Vue 3의 Composition API(컴포지션 API)는 이 과정의 각 시점에 onMounted, onUpdated, onUnmounted 같은 훅 함수를 등록해 부수 작업을 실행할 수 있게 한다. 라이프사이클을 정확히 이해하면 데이터 요청, DOM 접근, 자원 정리를 각각 올바른 시점에 배치할 수 있다.
라이프사이클의 네 단계
컴포넌트의 일생은 크게 생성(creation), 마운트(mount), 갱신(update), 소멸(unmount)의 네 단계로 나뉜다. 생성 단계에서는 컴포넌트 인스턴스가 만들어지고 반응형 상태가 준비된다. 마운트 단계에서는 템플릿이 렌더 함수로 실행되어 가상 DOM(virtual DOM)이 만들어지고 실제 DOM에 삽입된다. 갱신 단계는 반응형 의존성이 변할 때마다 반복되며, 새 가상 DOM과 이전 결과를 비교해 달라진 부분만 실제 DOM에 반영한다. 소멸 단계에서는 컴포넌트가 DOM에서 제거되면서 감시자(watcher), 이벤트 리스너, 자식 컴포넌트가 함께 정리된다.
Composition API의 라이프사이클 훅
Composition API에서는 script setup 블록 또는 setup 함수의 실행 자체가 생성 단계다. 그래서 Options API(옵션스 API)의 beforeCreate와 created에 해당하는 훅은 따로 존재하지 않고, 그 자리에서 하던 초기화 코드는 setup 본문에 그대로 쓰면 된다. 이후 시점은 다음 함수들로 등록한다.
- onBeforeMount, onMounted: DOM 삽입 직전과 직후에 호출된다. DOM 접근이 필요한 작업은 onMounted 이후에만 안전하다.
- onBeforeUpdate, onUpdated: 반응형 변화로 인한 재렌더링 직전과 직후에 호출된다.
- onBeforeUnmount, onUnmounted: 컴포넌트 제거 직전과 직후에 호출되며 자원 정리를 담당한다.
- onActivated, onDeactivated: keep-alive로 캐시된 컴포넌트가 화면에 나타나고 사라질 때 호출된다.
- onErrorCaptured: 자식 컴포넌트에서 전파된 오류를 가로챌 때 쓴다.
Options API와의 대응 관계
Vue 2 시절부터 쓰이던 Options API의 라이프사이클 옵션은 Composition API 훅과 다음처럼 대응한다. Vue 3에서 beforeDestroy와 destroyed가 beforeUnmount와 unmounted로 이름이 바뀐 점도 함께 기억해 두면 좋다.
| Options API | Composition API | 시점 |
|---|---|---|
| beforeCreate, created | setup 본문 | 인스턴스 생성과 상태 초기화 |
| beforeMount | onBeforeMount | DOM 삽입 직전 |
| mounted | onMounted | DOM 삽입 직후 |
| beforeUpdate | onBeforeUpdate | 재렌더링 직전 |
| updated | onUpdated | 재렌더링 직후 |
| beforeUnmount | onBeforeUnmount | 제거 직전 |
| unmounted | onUnmounted | 제거 직후 |
단계별 활용 예시
가장 흔한 조합은 onMounted에서 데이터를 불러오고 onUnmounted에서 타이머나 구독을 해제하는 패턴이다.
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const items = ref([]);
let timer = null;
async function refresh() {
const res = await fetch('/api/items');
items.value = await res.json();
}
onMounted(() => {
refresh();
timer = setInterval(refresh, 5000);
});
onUnmounted(() => {
clearInterval(timer);
});
</script>
타이머, 웹소켓, 전역 이벤트 리스너처럼 컴포넌트 바깥에 남는 자원은 반드시 onUnmounted에서 해제해야 한다. 정리를 빠뜨리면 컴포넌트가 사라진 뒤에도 콜백이 계속 실행되어 메모리 누수와 예측하기 어려운 오류로 이어진다.
주의할 점
- onUpdated 안에서 반응형 상태를 변경하면 다시 갱신이 일어나 무한 루프에 빠질 수 있다. 갱신 후 DOM을 읽는 용도로만 쓰는 것이 안전하다.
- 서버 사이드 렌더링(Server-Side Rendering) 환경에서는 서버에서 setup만 실행되고 onMounted 이후의 훅은 브라우저에서만 호출된다. window 같은 브라우저 전용 API 접근은 onMounted 안에 두어야 한다.
- keep-alive로 캐시된 컴포넌트는 화면에서 사라져도 언마운트되지 않으므로, 표시 여부에 따른 작업은 onActivated와 onDeactivated로 처리한다.
- 라이프사이클 훅은 setup의 동기 실행 중에 등록해야 한다. await 뒤에 등록하면 현재 컴포넌트 인스턴스와 연결되지 않아 경고와 함께 무시된다.
면접에서 이렇게 물어본다
- Composition API에 beforeCreate와 created에 해당하는 훅이 없는 이유는 무엇인가.
- 데이터 요청을 setup 본문과 onMounted 중 어디에서 하는지, 두 위치의 차이는 무엇인지 설명해 보라.
- onUnmounted에서 정리해야 하는 자원의 예를 들고, 정리하지 않으면 어떤 문제가 생기는가.
- keep-alive로 감싼 컴포넌트의 라이프사이클은 일반 컴포넌트와 어떻게 다른가.
- SSR 환경에서 호출되지 않는 라이프사이클 훅은 무엇이며 왜 그런가.
React / Vue에서 같이 읽기
- React Fragment: 불필요한 래퍼 없이 요소를 묶는 방법React Fragment는 여러 자식 요소를 추가 DOM 노드 없이 하나로 묶어 반환하게 해 주는 문법 요소다. 하나의 루트 요소 제약을 래퍼 없이 해결해 DOM 깊이와 CSS 레이아웃 문제를 예방하는 원리와 key 사용법을 정리한다.
- React Hook: 함수 컴포넌트의 상태와 로직 재사용React Hook은 함수 컴포넌트에서 상태 관리와 사이드 이펙트 처리를 가능하게 하는 함수들의 모음이다. 훅의 등장 배경, 호출 순서 기반 동작 원리와 규칙, 커스텀 훅을 통한 로직 재사용까지 면접 관점에서 정리한다.
- React와 Spring Boot 연동 구조: CORS, 프록시, 배포 전략React SPA와 Spring Boot REST API 서버를 분리해 구성하는 아키텍처를 다룬다. 개발 환경의 CORS와 프록시 설정, 정적 빌드 산출물의 통합 서빙과 분리 서빙 전략, 새로고침 404 해결까지 원리 중심으로 설명한다.
- Vue 3와 Firebase 이메일 인증: 토큰 기반 인증 흐름Firebase Authentication은 이메일 인증을 서버 구현 없이 제공하는 관리형 인증 서비스다. ID 토큰과 리프레시 토큰의 흐름, Vue 3 컴포저블 통합, 라우터 가드와 세션 유지, 보안 주의점을 원리 중심으로 정리한다.
이 개념, 내 코드에서는 어떻게 물어볼까요
데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.
공고 넣고 시작하기