티스토리 뷰
메모리 누수란?
더 이상 사용하지 않는 메모리가 해제되지 않고 계속 쌓이는 현상
증상
- 페이지가 점점 느려짐
- 탭을 오래 켜두면 브라우저 멈춤
- 모바일에서 앱이 강제 종료됨
주요 원인
1. Event Listener 정리 X
// 메모리 누수
export default {
mounted() {
window.addEventListener('scroll', this.handleScroll);
}
// 컴포넌트 파괴 시 이벤트 리스너가 남아있음!
}
// 올바른 방법
export default {
mounted() {
window.addEventListener('scroll', this.handleScroll);
},
unmounted() {
window.removeEventListener('scroll', this.handleScroll);
}
}
Vue3
import { onMounted, onUnmounted } from 'vue';
export default {
setup() {
const handleScroll = () => {
console.log('scrolling');
};
onMounted(() => {
window.addEventListener('scroll', handleScroll);
});
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
});
}
}
2. Timer 정리 X
// 메모리 누수
export default {
mounted() {
setInterval(() => {
this.updateData();
}, 1000);
}
}
// 올바른 방법
export default {
data() {
return {
timer: null
};
},
mounted() {
this.timer = setInterval(() => {
this.updateData();
}, 1000);
},
unmounted() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
}
Composable
// composables/useInterval.js
import { onUnmounted } from 'vue';
export const useInterval = (callback, delay) => {
const timer = setInterval(callback, delay);
onUnmounted(() => {
clearInterval(timer);
});
return timer;
};
// 사용
setup() {
useInterval(() => {
console.log('tick');
}, 1000);
}
3. DOM 참조 보관
// 메모리 누수
const elements = [];
document.querySelectorAll('.item').forEach(el => {
elements.push(el); // DOM 요소가 제거되어도 참조가 남아있음
});
// 올바른 방법 - WeakMap/WeakSet 사용
const elements = new WeakSet();
document.querySelectorAll('.item').forEach(el => {
elements.add(el); // DOM 제거 시 자동으로 가비지 컬렉션됨
});
WeakMap/WeakSet
// 일반 Map/Set
const map = new Map();
const set = new Set();
let obj = { name: 'Kim' };
map.set(obj, 'value');
set.add(obj);
obj = null; // Map/Set에 참조가 남아있어서 메모리 해제 안 됨
// WeakMap/WeakSet
const weakMap = new WeakMap();
const weakSet = new WeakSet();
let obj = { name: 'Kim' };
weakMap.set(obj, 'value');
weakSet.add(obj);
obj = null; // 자동으로 WeakMap/WeakSet에서도 제거됨 (가비지 컬렉션)
핵심 차이점
| 특징 | Map/Set | WeakMap/WeakSet |
| 키 타입 | 모든 타입 | 객체만 |
| 메모리 | 계속 유지 | 자동 해제 |
| 순회 | 가능 | 불가능 |
| size | 있음 | 없음 |
'JavaScript' 카테고리의 다른 글
| TypeScript 활용 팁 (0) | 2026.02.23 |
|---|---|
| Javascript - ECMAScript 버전 히스토리 (0) | 2026.02.05 |
| JavaScript - Canvas 차트 모바일 화질 저하 문제 (0) | 2024.04.26 |
| JavaScript - 전화번호에 하이픈 추가 (0) | 2024.03.28 |
| JavaScript - 한글 조사 처리 (0) | 2024.03.15 |