본문 바로가기
Coding Study/FrontEnd Study Note

자바스크립트에서 메모리 누수가 발생하는 상황들

by bell_one 2026. 3. 4.

1. 의도치 않은 전역 변수 (Global Variables)

자바스크립트에서 선언 키워드(let, const, var) 없이 변수를 할당하면 브라우저의 경우 window 객체에 바인딩됩니다. 전역 변수는 페이지가 닫힐 때까지 메모리에 상주하므로 GC의 수거 대상에서 제외됩니다.

function leak() {
  // 실수로 선언 없이 할당함 -> window.bigData가 되어버림
  bigData = new Array(1000000).fill('leak'); 
}

2. 잊혀진 타이머와 콜백 (Forgotten Timers)

setInterval이나 setTimeout을 설정하고 적절히 해제하지 않으면, 그 안에서 참조하는 변수들은 타이머가 도는 동안 계속 메모리에 남습니다.

const someResource = getData();

// setInterval이 멈추지 않는 한, someResource는 영원히 해제되지 않음
setInterval(() => {
  const node = document.getElementById('node');
  if (node) {
    node.innerHTML = JSON.stringify(someResource);
  }
}, 1000);

// 

해결: clearInterval이나 clearTimeout을 명시적으로 호출해야 합니다.


3. 해제되지 않은 이벤트 리스너 (Uncleared Event Listeners)

특히 현대적인 프론트엔드 프레임워크(React, Vue 등)에서 컴포넌트가 사라질 때(unmount), window나 document에 등록했던 이벤트 리스너를 제거하지 않으면 해당 컴포넌트의 클로저와 데이터가 메모리에 계속 남습니다.

window.addEventListener('resize', () => {
  console.log(this.hugeData); // 컴포넌트가 사라져도 이 함수는 계속 살아있음
});

4. 탈착된 DOM 노드 참조 (Detached DOM Nodes)

DOM 트리에서는 삭제되었지만, 자바스크립트 변수 어딘가에 해당 노드를 담고 있는 경우입니다. 이를 Detached DOM이라고 부르며, 브라우저는 이 노드가 나중에 다시 쓰일지 모르니 메모리에서 지우지 못합니다.

 
let elements = {
  button: document.getElementById('main-button')
};

// 실제 DOM에서는 삭제했지만...
document.body.removeChild(document.getElementById('main-button'));

// elements.button이 여전히 노드를 참조하고 있어서 메모리 누수 발생!
// 

5. 클로저(Closure)의 잘못된 사용

클로저는 외부 함수의 변수를 기억하는 유용한 기능이지만, 큰 객체를 참조하는 클로저를 의도치 않게 계속 들고 있으면 메모리가 낭비됩니다.

let leak = function() {
  let heavyData = new Array(1000000); // 엄청 큰 데이터
  
  return function() {
    // 이 내부 함수가 살아있는 한 heavyData는 죽지 않음
    return heavyData;
  };
};

💡 예방을 위한 팁

  • Strict Mode ('use strict'): 선언되지 않은 변수 할당을 에러로 처리해 전역 변수 생성을 막아줍니다.
  • WeakMap, WeakSet 활용: 객체를 키로 사용하되, 참조가 끊기면 자동으로 GC가 수거할 수 있게 해주는 약한 참조(Weak Reference) 자료구조를 사용하세요.
  • Chrome 개발자 도구: 'Memory' 탭의 Heap Snapshot을 찍어보면 어떤 객체가 비정상적으로 자리를 차지하는지 추적할 수 있습니다.

'Coding Study > FrontEnd Study Note' 카테고리의 다른 글

Next.js가 제공하는 캐싱  (0) 2026.03.04
package.json 의존성 삼형제  (0) 2026.03.04
JSX란 무엇인가?  (0) 2026.02.26
CSS 명시도  (0) 2026.02.26
동적 타입 언어와 정적 타입 언어  (0) 2026.02.23