♻️ DOM 참조와 비동기 로직에서의 메모리 주의점 – 실무 중심 정리
자바스크립트는 비동기 로직과 DOM 참조를 함께 사용할 때 메모리 누수가 자주 발생합니다.
이 글에서는 이벤트 리스너, setTimeout, 클로저, 비동기 콜백 등에서 발생할 수 있는 메모리 유지 원인과 방지 전략을 정리합니다.
1. 문제: DOM 요소가 제거됐는데 메모리에는 남아있다?
function init() {
const el = document.getElementById("btn");
el.addEventListener("click", () => {
alert("clicked");
});
el.remove(); // ❌ 하지만 이벤트 리스너는 여전히 el을 참조
}
👉 이벤트 리스너 내부에서 el을 참조하면, 요소가 제거돼도 GC가 되지 않습니다.
2. 해결: 리스너 제거는 반드시!
function cleanup(el, handler) {
el.removeEventListener("click", handler);
el.remove(); // ✅ 이제 GC 가능
}
removeEventListener
를 빼먹으면 메모리 누수의 대표적인 원인이 됩니다.
3. setTimeout / setInterval 안의 DOM 참조
const el = document.getElementById("box");
setTimeout(() => {
el.style.display = "none"; // ❌ el이 계속 메모리에 남음
}, 5000);
✅ 해결 방법:
setTimeout(() => {
const el = document.getElementById("box");
if (el) el.style.display = "none";
}, 5000);
👉 필요할 때만 DOM을 다시 가져오고, 오래 참조하지 않도록 합니다.
4. 비동기 콜백에서 DOM 참조 유지
function fetchAndUpdate(el) {
fetch("/api/data")
.then(res => res.json())
.then(data => {
el.textContent = data.message; // ❌ el이 클로저로 묶임
});
}
✅ 개선 방법:
function fetchAndUpdate(id) {
fetch("/api/data")
.then(res => res.json())
.then(data => {
const el = document.getElementById(id);
if (el) el.textContent = data.message;
});
}
👉 엘리먼트 참조는 짧게 유지하고, ID나 data-attr로 필요 시 다시 조회하는 패턴이 좋습니다.
5. MutationObserver나 IntersectionObserver
이런 관찰자 API도 콜백 내부에서 DOM을 계속 참조하면 누수가 발생할 수 있습니다.
✅ 반드시 해제 필요:
const observer = new MutationObserver(callback);
observer.observe(targetNode, { childList: true });
// 나중에 해제
observer.disconnect();
6. 메모리 누수 방지 체크리스트 ✅
- ☑ 이벤트 리스너는
removeEventListener
로 제거 - ☑ 타이머(
setTimeout
,setInterval
)는clearTimeout
,clearInterval
호출 - ☑ 비동기 콜백 안에서는 DOM 참조 최소화
- ☑ 필요 시 ID, data-attr로 DOM을 재조회
- ☑
MutationObserver
등은 disconnect로 해제
📌 마무리
자바스크립트는 DOM과 비동기 처리가 밀접하게 얽혀 있기 때문에,
요소를 직접 참조하는 클로저나 콜백, 타이머는 메모리 누수를 유발할 수 있습니다.
코드를 작성할 때는 참조 범위를 최소화하고, 리스너/관찰자 해제를 습관화하는 것이 중요합니다.
이로써 챕터 8: 메모리 관리와 성능 최적화가 마무리되었습니다.
다음 챕터 9에서는 고급 함수 패턴과 함수형 프로그래밍 개념으로 넘어갑니다. 첫 글은 고차 함수(Higher-Order Function)의 개념과 예제입니다.
'language > javascript' 카테고리의 다른 글
🪄 커링(Currying)과 부분 적용(Partial Application) – 개념과 실전 패턴 비교 (0) | 2025.05.11 |
---|---|
🪄 고차 함수(Higher-Order Function)의 개념과 예제 (0) | 2025.05.11 |
♻️ WeakMap을 활용한 안전한 참조 관리 – 클로저, 캐시, 메모리 누수 방지 전략 (0) | 2025.05.11 |
♻️ 클로저와 메모리 누수 이슈 – 원인과 방지 방법 완전 정리 (0) | 2025.05.11 |
♻️ 가비지 컬렉션(GC) 작동 원리와 메모리 누수 방지 전략 (0) | 2025.05.11 |
댓글