IT & 웹개발

JavaScript 메모리 관리와 가비지 컬렉션(Garbage Collection) 이해하기

kkwako 2025. 4. 2. 16:30

1. 개요

JavaScript는 자동 메모리 관리 기능을 제공하는 Garbage Collection(GC) 방식을 사용한다. 덕분에 개발자가 직접 메모리를 할당하고 해제할 필요는 없지만, 불필요한 메모리 사용과 메모리 누수(memory leak) 문제는 여전히 발생할 수 있다.

본 글에서는 JavaScript의 메모리 관리 방식과 가비지 컬렉션(GC) 동작 원리, 그리고 메모리 누수를 방지하는 최적화 방법에 대해 알아본다.


2. JavaScript의 메모리 관리 과정

JavaScript에서 메모리는 할당 → 사용 → 해제의 단계를 거친다.

(1) 메모리 할당 (Allocation)

JavaScript에서는 변수를 선언하면 자동으로 메모리를 할당한다.

javascript
복사편집
let num = 10; // 숫자 타입 변수 할당 let obj = { name: "Alice", age: 25 }; // 객체 생성 및 메모리 할당

객체(Object)와 배열(Array), 함수(Function) 등은 Heap(힙) 메모리에 저장되며, 기본 자료형(숫자, 문자열, 불리언 등)은 Stack(스택) 메모리에 저장된다.

(2) 메모리 사용 (Usage)

JavaScript는 객체에 대한 참조(Reference)를 유지하면서 데이터를 처리한다.

javascript
복사편집
let user = { name: "Bob" }; let anotherUser = user; // 동일한 객체를 참조 console.log(anotherUser.name); // "Bob"

이처럼 객체를 다른 변수에 할당하면 새로운 복사본이 생성되는 것이 아니라 같은 메모리 주소를 가리키게 된다.

(3) 메모리 해제 (Deallocation)

JavaScript는 가비지 컬렉션(GC)을 통해 더 이상 필요하지 않은 객체를 자동으로 제거한다. 하지만 모든 메모리를 자동으로 해제하는 것은 아니므로, 개발자가 직접 메모리 누수를 방지하는 전략을 고려해야 한다.


3. 가비지 컬렉션(GC) 동작 원리

JavaScript의 가비지 컬렉션은 **참조 카운트(Reference Counting)**와 마크 앤 스위프(Mark-and-Sweep) 방식을 사용한다.

(1) 참조 카운트(Reference Counting)

객체가 참조될 때마다 참조 카운트가 증가하고, 참조가 제거되면 카운트가 감소한다.

javascript
복사편집
let obj1 = { value: 100 }; let obj2 = obj1; // obj1을 참조 obj1 = null; // obj1의 참조가 사라졌지만 obj2가 여전히 참조 중

위와 같이 obj2가 obj1을 계속 참조하고 있다면 객체는 메모리에서 해제되지 않는다. 이러한 현상을 메모리 누수라고 한다.

(2) 마크 앤 스위프(Mark-and-Sweep)

현대 JavaScript 엔진은 마크 앤 스위프(Mark-and-Sweep) 알고리즘을 사용하여 불필요한 객체를 주기적으로 제거한다.

  1. Reachable(도달 가능한) 객체를 찾는다.
  2. 도달할 수 없는 객체를 **가비지(garbage)**로 표시한다.
  3. 가비지로 표시된 객체를 메모리에서 해제한다.
javascript
복사편집
function createUser() { let user = { name: "Charlie" }; // 함수 내에서 객체 생성 } createUser(); // 함수 실행 후 user 객체는 더 이상 접근할 수 없음 // user 객체는 GC에 의해 자동 해제됨

위의 user 객체는 함수가 종료된 후 더 이상 참조되지 않으므로 가비지 컬렉션에 의해 자동 해제된다.


JavaScript 메모리 관리와 가비지 컬렉션(Garbage Collection) 이해하기

4. 메모리 누수가 발생하는 원인

JavaScript에서 메모리 누수가 발생하는 주요 원인은 다음과 같다.

(1) 전역 변수 사용

전역 변수는 프로그램이 종료될 때까지 메모리에 남아 있어, 메모리 누수를 유발할 수 있다.

javascript
복사편집
window.globalVar = "I am a global variable";

해결 방법: 전역 변수를 줄이고, let과 const를 사용하여 블록 범위(scope)를 제한한다.

(2) 클로저(Closure)로 인한 메모리 누수

클로저는 함수가 종료된 후에도 내부 변수를 참조할 수 있어, 불필요한 메모리를 점유할 수 있다.

javascript
복사편집
function createCounter() { let count = 0; return function () { count++; console.log(count); }; } let counter = createCounter(); // count 변수는 계속 메모리에 남아 있음

해결 방법: 클로저를 사용할 때 필요하지 않은 변수는 null로 설정하여 메모리에서 해제한다.

javascript
복사편집
counter = null;

(3) DOM 요소 참조 유지

이벤트 리스너가 제거되지 않고 남아 있으면, 해당 DOM 요소는 메모리에서 해제되지 않는다.

javascript
복사편집
let button = document.getElementById("myButton"); button.addEventListener("click", function () { console.log("Clicked!"); });

해결 방법: 이벤트 리스너를 제거하여 DOM 요소가 메모리에서 해제되도록 한다.

javascript
복사편집
button.removeEventListener("click", handler); button = null;

(4) 타이머(setInterval, setTimeout) 미삭제

setInterval이 실행 중인데 이를 중단하지 않으면 메모리 누수가 발생할 수 있다.

javascript
복사편집
let intervalId = setInterval(() => { console.log("Running..."); }, 1000);

해결 방법: clearInterval(intervalId)를 호출하여 타이머를 정리한다.

javascript
복사편집
clearInterval(intervalId); intervalId = null;

5. 메모리 최적화 및 관리 전략

(1) 변수를 더 이상 사용하지 않을 경우 null 할당

객체가 더 이상 필요하지 않다면 null을 할당하여 가비지 컬렉션이 처리할 수 있도록 한다.

javascript
복사편집
let data = { name: "Alice" }; data = null; // 가비지 컬렉션 대상이 됨

(2) 이벤트 리스너 정리

사용하지 않는 이벤트 리스너를 반드시 제거한다.

javascript
복사편집
element.removeEventListener("click", eventHandler);

(3) WeakMap과 WeakSet 활용

WeakMap과 WeakSet은 자동으로 가비지 컬렉션이 가능하여 메모리 누수를 방지할 수 있다.

javascript
복사편집
let weakMap = new WeakMap(); let obj = {}; weakMap.set(obj, "Some value"); obj = null; // obj가 해제되면 weakMap에서도 자동 제거됨

(4) setTimeout과 setInterval 정리

타이머를 사용할 때는 반드시 정리하는 습관을 들인다.

javascript
복사편집
let timer = setTimeout(() => console.log("Hello"), 5000); clearTimeout(timer);

6. 결론

JavaScript는 자동 메모리 관리를 제공하지만, 메모리 누수를 방지하는 습관과 최적화 전략이 필요하다.

주요 메모리 관리 방법

  • 불필요한 전역 변수 사용 자제
  • 클로저를 조심하여 필요 없는 참조를 제거
  • setInterval, setTimeout 제거
  • 이벤트 리스너 해제
  • WeakMap과 WeakSet 활용

이러한 전략을 실천하면 메모리 누수를 방지하고 JavaScript 애플리케이션의 성능을 최적화할 수 있다.