본문 바로가기

JAVASCRIPT

자바스크립트 가비지 콜렉션과 순환참조

가비지 콜렉션이란?

가비지 콜렉터가 더이상 사용되지 않는 메모리를 해제하는 것이다.

 

가비지 콜렉션 예시

아래 글에서의 예시인데, 이 글만으로는 이해하기 힘든 부분이 있어 설명을 추가해보았다.

 

자바스크립트의 메모리관리 - JavaScript | MDN

C 언어같은 저수준 언어에서는 메모리 관리를 위해 malloc() 과 free()를 사용한다. 반면, 자바스크립트는 객체가 생성되었을 때 자동으로 메모리를 할당하고 쓸모 없어졌을 때 자동으로 해제한

developer.mozilla.org

 

 

var x = {
  a: {
    b: 2
  }
};              // 1

 

{ b: 2 } 오브젝트는 b 오브젝트, { a: {b: 2} } 오브젝트는 a 오브젝트라 하겠다.

메모리에 b 오브젝트를 참조하는 a 오브젝트가 생긴다. x 변수는 a 오브젝트를 참조한다. 

가비지 콜렉션이 수행될 메모리는 없다.

 

 

var y = x;      // 2

 

y 변수는 x의 값, 즉 a 오브젝트 를 참조한다.

 

 

x = 1;          // 3

 

x 변수에 1을 할당한다. 이때, 원래 참조하던 메모리의 값을 지우고 값 1을 등록하는 것이 아니라, 값 1을 위한 새로운 메모리를 할당한다.

y는 여전히 a 오브젝트를 참조하고 있다.

 

var z = y.a;    // 4

 

변수 z는 a 오브젝트의 프로퍼티 a를 참조한다. 

 

 

y = "heyyy";    // 5

 

y는 새로운 값 "heyyy"를 참조한다. z가 여전히 a 오브젝트의 프로퍼티 a를 참조하고 있으므로 가비지 컬렉션이 수행되지 않는다.

 

 

z = null;       // 6

z가 null 값을 참조하면서 a 오브젝트를 참조하는 변수는 하나도 없다. a 오브젝트, b 오브젝트에 대한 가비지 콜렉션이 수행된다.

 

 

가비지 콜렉션 알고리즘

옛날에는 가비지 콜렉션 알고리즘으로 Reference-counting 알고리즘이 쓰였다. 값을 참조하는 변수가 없으면 가비지 콜렉션을 수행하는 것인데, 이 알고리즘에는 순환 참조로 인한 메모리 누수 문제가 있다.

 

function f(){ 
	var o = {}; 
	var o2 = {}; 

	o.a = o2; // o는 o2를 참조한다. 
	o2.a = o; // o2는 o를 참조한다. 
}

f();

 

1번이 f 함수를 실행하는 중의 상태이고, 2번이 f 함수가 종료된 시점이다. 함수가 종료되면서 두 오브젝트를 참조하는 o와 o2 변수가 사라졌음에도, 서로가 서로를 참조하고 있다. 그래서 실제로는 사용되지 않는 메모리이지만 메모리가 반환되지 않는다.

 

이에 대한 대안으로 Mark-and-sweep 알고리즘을 사용한다. 이 알고리즘은 주기적으로 전역변수들의 집합인 roots부터 시작해서, 전역변수들이 참조하고 있는 오브젝트, 그리고 그 오브젝트가 참조하는 오브젝트를 탐색하며 "닿을 수 있음" 표시를 한다. 그리고 닿을 수 없는 오브젝트에 대해 가비지 콜렉션을 수행한다.

'JAVASCRIPT' 카테고리의 다른 글

DOM과 Virtual DOM  (0) 2022.01.16
자바스크립트 Promise  (0) 2022.01.14
자바스크립트 Execution Context  (0) 2021.12.08
자바스크립트 변수 호이스팅  (0) 2021.12.04
JavaScript Closure  (0) 2021.04.21