안녕하세요, ‘코딩하는곰’입니다. 오늘은 Vue.js와 Angular의 라이프사이클 훅 중에서도 특히 중요한 updated와 destroyed(또는 Angular의 ngOnDestroy) 훅에 대해 깊이 있게 파헤쳐보려고 합니다. 싱글 페이지 애플리케이션(SPA)을 개발하다 보면, 데이터가 변경된 직후에 추가 로직을 실행해야 하거나, 컴포넌트가 사라질 때 리소스를 깔끔하게 정리해야 하는 상황이 반드시 찾아옵니다. 이러한 순간들을 어떻게 우아하게 처리할 수 있을지, 두 프레임워크의 관점에서 비교 분석하고 실전 예제를 통해 완벽하게 이해해보는 시간을 가져보겠습니다. SEO를 고려한 효율적인 코드 구조가 어떻게 애플리케이션 성능과 유지보수성까지 좌우하는지 함께 살펴볼까요?
updated 훅의 역할Vue.js와 Angular 모두 컴포넌트 기반 아키텍처를 채택하고 있으며, 각 컴포넌트는 생성부터 소멸까지의 명확한 생명주기(Lifecycle)를 가집니다. 이 생명주기의 각 단계에서 호출되는 함수가 바로 ‘라이프사이클 훅’입니다. 이 훅들을 잘 활용하면 특정 시점에 원하는 코드를 실행할 수 있어, 애플리케이션의 동작을 정교하게 제어할 수 있습니다.
오늘 첫 번째로 집중할 updated 훅(Vue.js)은 컴포넌트의 데이터가 변경되어, 가상 DOM이 재렌더링되고 실제 DOM에 패치된 직후에 호출됩니다. 쉽게 말해, 화면이 업데이트된 직후에 실행해야 할 코드를 여기에 작성하면 됩니다. Angular에는 updated와 정확히 일치하는 훅은 없지만, 비슷한 역할을 하는 ngAfterViewChecked나 변화 감지 체크 후 로직을 수행하는 방법들이 있습니다.
updated 훅의 주요 사용 사례:
updated 훅에서 이 로직을 처리할 수 있습니다.// Vue.js - updated 훅 사용 예시export default {data() {return {chartData: [],myChart: null};},mounted() {// 차트 초기화this.myChart = new Chart(this.$refs.canvas, { type: 'line', data: { datasets: [] } });},updated() {// chartData가 변경되어 DOM이 업데이트된 후, 차트를 갱신합니다.if (this.myChart) {this.myChart.data.datasets[0].data = this.chartData;this.myChart.update(); // 차트 라이브러리의 업데이트 메서드 호출}// 추가로, 업데이트 후 스크롤을 최하단으로 이동const container = this.$refs.messageContainer;if (container) {container.scrollTop = container.scrollHeight;}}}
🤖 AI와 머신러닝 개발에 관심이 있다면, (자바 기초) 접근 제어자 완벽 정리 - public, private, protected 차이를 참고해보세요.
destroyed/ngOnDestroy 훅: 리소스 누수 방지의 핵심컴포넌트가 인스턴스에서 제거된 후, 즉 ‘파괴’된 후에 호출되는 훅입니다. Vue.js에서는 destroyed, Angular에서는 ngOnDestroy입니다. 이 훅은 메모리 누수(Memory Leak)를 방지하기 위해 반드시 신경 써야 할 곳입니다. SPA에서는 컴포넌트가 화면에서 사라져도 JavaScript 인스턴스가 완전히 정리되지 않으면, 이벤트 리스너나 인터벌 타이머, 외부 라이브러리 인스턴스 등이 계속 메모리에 남아 애플리케이션 성능을 서서히 저하시킬 수 있습니다.
destroyed/ngOnDestroy 훅의 필수 정리 작업:
addEventListener로 등록한 커스텀 이벤트나 전역 이벤트는 반드시 removeEventListener로 제거해야 합니다.setInterval, setTimeout으로 생성한 타이머는 clearInterval, clearTimeout으로 해제해야 합니다.destroy() 메서드를 제공한다면 호출해줍니다.// Angular - ngOnDestroy 훅 사용 예시import { Component, OnDestroy, OnInit } from '@angular/core';import { Subscription, interval } from 'rxjs';@Component({selector: 'app-timer',template: `<p>{{ count }}</p>`})export class TimerComponent implements OnInit, OnDestroy {count = 0;private timerSubscription!: Subscription; // 구독 객체 저장private resizeListener!: () => void; // 리스너 제거를 위한 참조 저장ngOnInit() {// 1초마다 카운트 증가 (RxJS 인터벌)this.timerSubscription = interval(1000).subscribe(() => this.count++);// 전역 resize 이벤트 리스너 등록this.resizeListener = () => console.log('Window resized');window.addEventListener('resize', this.resizeListener);}ngOnDestroy() {// 1. RxJS 구독 해제 (메모리 누수 방지 핵심!)if (this.timerSubscription) {this.timerSubscription.unsubscribe();}// 2. 이벤트 리스너 제거window.removeEventListener('resize', this.resizeListener);console.log('TimerComponent가 파괴되었고, 모든 리소스가 정리되었습니다.');}}
센스 있는 닉네임을 만들고 싶을 때는 즐겨찾기 기능까지 지원하는 랜덤 닉네임 생성기가 유용합니다.
두 프레임워크의 접근 방식을 비교해보면, 핵심 철학은 동일하지만 구현과 네이밍에 차이가 있습니다. Vue.js는 updated, destroyed와 같은 보다 직관적인 이름을 사용하는 반면, Angular는 ngOnDestroy와 같이 접두사(ng)를 붙인 인터페이스 구현 방식을 선호합니다. 이 차이는 각 프레임워크의 디자인 패턴과 철학을 반영합니다.
실전에서 자주 마주치는 통합 시나리오와 해결 패턴:
updated 훅에서 Vuex 상태 변화를 감지해 사이드 이펙트를 실행할 수 있지만, 대부분의 경우 Vuex의 액션(Actions)이나 게터(Getters)를 이용하는 것이 더 낫습니다.destroyed/ngOnDestroy에서는 Vuex의 subscribe 메서드로 등록한 리스너를 반드시 해제해야 합니다.updated 훅에서 실행하는 비동기 데이터 fetching이나 DOM 조작은 서버 사이드 렌더링(SSR) 환경에서 주의해야 합니다. mounted 또는 클라이언트 사이드에서만 실행되도록 조건을 추가하는 것이 좋습니다.AbortController 사용)을 destroyed 훅에 추가하면, 사용자 경험과 서버 자원을 모두 아낄 수 있습니다.updated 훅은 데이터가 변경될 때마다 매우 빈번히 호출될 수 있습니다. 이 훅 내부의 로직이 무겁다면, debounce나 throttle 기법을 적용하거나, 정말 필요한 데이터 변경인지 확인하는 로직(if (this.previousData !== this.currentData))을 추가하는 것이 좋습니다.v-once 디렉티브나 Angular의 OnPush 변화 감지 전략을 활용하면 불필요한 updated 사이클 자체를 줄일 수 있어 성능에 큰 도움이 됩니다.// Vue.js 실전 패턴: 디바운스 적용 및 조건부 업데이트import { debounce } from 'lodash-es';export default {data() {return {searchQuery: '',searchResults: [],previousQuery: '' // 이전 값 저장};},created() {// 디바운스 처리된 검색 함수 생성this.debouncedSearch = debounce(this.performSearch, 300);},watch: {searchQuery(newVal, oldVal) {this.debouncedSearch();}},updated() {// 실제로 검색어가 바뀌었을 때만 DOM 관련 작업 수행 (성능 최적화)if (this.previousQuery !== this.searchQuery) {this.previousQuery = this.searchQuery;this.scrollToTopOfResults(); // DOM 조작 함수}},methods: {performSearch() {// ... API 호출 로직},scrollToTopOfResults() {const el = this.$refs.results;if (el) el.scrollIntoView({ behavior: 'smooth' });}},destroyed() {// 디바운스된 함수의 pending 타이머 취소this.debouncedSearch.cancel();}}
디자인을 해치지 않으면서도 브랜드 이미지를 강조하고 싶다면, 로고 삽입이 가능한 QR 코드 생성기를 활용해보는 것이 좋습니다.
지금까지 Vue.js의 updated, destroyed 훅과 Angular의 ngOnDestroy 훅을 중심으로 데이터 변경 후처리와 리소스 정리의 모든 것을 살펴보았습니다. 이러한 라이프사이클 훅을 올바르게 이해하고 활용하는 것은 단순히 기능을 구현하는 것을 넘어, 안정적이고 효율적이며 유지보수가 쉬운 프로페셔널한 애플리케이션을 만드는 데 가장 기초적이면서도 핵심적인 단계입니다.
특히 destroyed 훅에서의 정리 작업은 사소해 보이지만 장기적으로 애플리케이션의 건강 상태를 결정합니다. 오늘 배운 내용을 바탕으로 여러분의 프로젝트 코드를 다시 한번 살펴보시기 바랍니다. ‘혹시 정리하지 않은 리소스는 없는가?’ ‘이 업데이트 로직은 더 효율적으로 작성할 수 없을까?‘라는 질문을 던져보세요.
Vue.js와 Angular의 세계는 계속해서 진화하고 있지만, 컴포넌트의 생명주기라는 근본적인 개념은 변하지 않을 것입니다. 이 글을 읽으신 여러분이 이 개념을 튼튼히 다져, 더욱 견고한 웹 애플리케이션을 구축하는 데 도움이 되었으면 합니다. 다음 시간에는 또 다른 유용한 개발 팁으로 찾아뵙겠습니다. 감사합니다! - 코딩하는곰
두뇌 건강을 위한 재미있는 퍼즐 게임을 찾고 있다면, 크립토 할아버지의 스토리와 함께하는 스도쿠 저니를 추천합니다.
