♻️ 가비지 컬렉션(GC) 작동 원리와 메모리 누수 방지 전략
자바스크립트는 메모리를 자동으로 관리해주는 가비지 컬렉션(Garbage Collection) 기능을 내장하고 있습니다.
그러나 자동이라고 해서 완벽하지는 않으며, 실수로 인해 메모리 누수(memory leak)가 발생할 수 있습니다.
이번 글에서는 GC의 작동 원리와 함께, 실무에서 자주 발생하는 누수 사례와 예방 방법을 정리합니다.
1. 자바스크립트의 메모리 구조
- 스택(Stack): 함수 호출과 지역 변수 저장 (고정 크기, 빠른 할당)
- 힙(Heap): 객체, 배열 등 동적 데이터 저장 (GC 대상)
가비지 컬렉션은 힙 영역의 메모리 정리를 담당하며, 더 이상 사용되지 않는 객체를 자동으로 해제합니다.
2. GC의 기본 원리 – 참조 카운트와 도달 가능성
✅ 오래된 방식: 참조 카운트
let a = {};
let b = a;
a = null;
// b가 여전히 a를 참조하므로 GC 대상 아님
✅ 현재는 대부분 “도달 가능성(Reachability)” 기준
루트 객체(window, globalThis)
에서부터 도달할 수 없는 객체는 GC 대상이 됩니다.
let user = {
name: "Alice"
};
user = null; // 👉 객체에 접근할 수 있는 경로가 사라짐 → GC 대상
3. 메모리 누수(Memory Leak)란?
더 이상 사용되지 않지만 해제되지 않고 메모리에 남아 있는 객체
가 계속해서 누적되는 현상입니다.
💥 대표적인 누수 예시
- 1️⃣ 전역 변수에 계속 값 저장
- 2️⃣ 이벤트 리스너를 제거하지 않음
- 3️⃣ 클로저 내부에 불필요한 참조 유지
- 4️⃣ DOM 요소 제거 후 참조 유지
4. 실무 예제: 누수 발생과 해결
❌ 누수 예시: 클로저로 인한 참조 유지
function setup() {
const bigData = new Array(1000000).fill("x");
return () => console.log("ready");
}
const handler = setup(); // bigData는 아직 메모리에 있음
✅ 해결: 불필요한 참조 제거
function setup() {
let bigData = new Array(1000000).fill("x");
const callback = () => console.log("ready");
bigData = null; // 수동으로 참조 제거
return callback;
}
5. 이벤트 리스너 해제는 필수
const el = document.querySelector("#btn");
el.addEventListener("click", onClick);
// 이후 버튼 제거
el.remove(); // ❌ 이벤트 리스너가 참조되고 있으면 GC 안 됨
// ✅ 리스너 먼저 제거
el.removeEventListener("click", onClick);
el.remove();
🧠 이벤트 핸들러, 타이머, 인터벌은 꼭 clear
또는 remove
해야 합니다.
6. WeakMap, WeakSet을 활용한 안전한 참조 관리
const cache = new WeakMap();
function remember(obj, value) {
cache.set(obj, value); // obj가 GC 되면 함께 사라짐
}
- key가 객체인 경우만 사용 가능
- 객체가 참조에서 사라지면 자동으로 메모리에서 제거됨
7. 메모리 누수 방지 체크리스트 ✅
- 전역 변수 남용 금지 (
let x
대신 필요한 스코프에 한정) - setTimeout, setInterval 해제 (
clearTimeout
,clearInterval
) - 이벤트 리스너 제거 (
removeEventListener
) - DOM 제거 시 객체 참조도 제거
- 대용량 배열, Map 등 클로저에서 오래 유지하지 않기
- WeakMap, WeakSet 활용
📌 마무리
자바스크립트의 가비지 컬렉션은 자동이지만, 누수는 개발자의 책임입니다.
도달 가능성
기반의 GC가 작동하기 때문에, 참조가 끊기지 않으면 메모리는 남습니다.
이벤트, 클로저, 전역 변수 등 참조를 적절히 해제하고 관리하는 습관이 중요합니다.
다음 글에서는 클로저와 메모리 누수 이슈를 집중적으로 살펴보며, 함수형 구조 내에서의 안전한 메모리 사용법을 정리합니다.
'language > javascript' 카테고리의 다른 글
♻️ WeakMap을 활용한 안전한 참조 관리 – 클로저, 캐시, 메모리 누수 방지 전략 (0) | 2025.05.11 |
---|---|
♻️ 클로저와 메모리 누수 이슈 – 원인과 방지 방법 완전 정리 (0) | 2025.05.11 |
📦 네임스페이스 충돌 방지 전략과 구조 설계 팁 (0) | 2025.05.10 |
📦 IIFE (즉시 실행 함수 표현식) 패턴 – 역사적 배경과 활용법 정리 (0) | 2025.05.10 |
📦 모듈 번들링의 원리 – Webpack, Vite, Tree-shaking 개념까지 완전 정리 (0) | 2025.05.10 |
댓글