Javascript Garbage Colector

IT공부중·2020년 8월 27일
0

JavsScript

목록 보기
11/22
post-thumbnail

자바스크립트는 저수준 언어와는 다르게 객체가 생성되었을 때 자동으로 메모리를 할당하고 쓸모 없어졌을 때 자동으로 해제한다(가비지 컬렉션).

메모리의 생명 주기는 프로그래밍 언어와 상관없이 비슷하다.

  1. 필요할때 할당한다.
  2. 사용한다. (읽기, 쓰기)
  3. 필요없어지면 해제한다.

3번의 과정인 할당된 메모리가 더 이상 필요없어졌을 때 해제하는 부분에서 문제가 많이 발생한다. "할당된 메모리가 필요없어 졌을 때"를 알아내기가 어렵기 때문이다.

Garbage Colertion

가비지 콜렉션 알고리즘의 핵심 개념은 참조이다. A라는 메모리를 통해 B라는 메모리에 접근할 수 있다면 "B는 A에 참조된다" 라고 한다. 예를 들어 모든 자바스크립트 오브젝트는 prototype 을 암시적으로 참조하고 그 오브젝트의 속성을 명시적으로 참조한다.

가장 대표적인 GC 알고리즘으로 2가지가 있다. 한번 알아보도록 하자.

참조세기(Reference-counting) 알고리즘

참조세기 알고리즘은 간단한 알고리즘이다. 이 알고리즘은 "더 이상 필요없는 오브젝트"를 "어떤 다른 오브젝트도 참조하지 않는 오브젝트"라고 정의한다. 이 오브젝트를 "가비지"라고 부르고 이를 참조하는 다른 오브젝트가 하나도 없을 경우 GC에서 수거해간다. 즉, 참조 되고 있는 수를 센다음에 1개라도 있을 경우 GC가 수거해가지 않고, 하나도 없을 경우 수거해가는 것이다.

하지만 한계가 있다. 순환 참조에서 에러가 발생한다. 서로가 서로를 참조하는 경우 더 이상 필요가 없어진 경우에도 참조 되고 있기 때문에 GC가 수거해가지 않는다.

IE 6,7은 해당 알고리즘을 사용한다.

표시하고 쓸기(Mark and Sweep) 알고리즘

Mark and Sweep 알고리즘은 참조세기 알고리즘의 한계를 극복하기 위해 나왔다.

이 알고리즘은 roots 라는 오브젝트의 집합을 가지고 있다. 즉 전역 변수들을 의미한다. 주기적으로 가비지 콜렉터는 roots로 부터 시작하여 roots가 참조하는 오브젝트들, roots가 참조하는 오브젝트가 참조하는 오브젝트들... 을 닿을 수 있는 오브젝트라고 표시한다. 즉, roots가 참조하고 있는 객체 그 객체가 참조하고 있는 객체 또 그 객체가 참조하고 있는 객체로 계속 타고 들어갈 수 있다. 이렇게 닿을 수 있는 오브젝트가 아닌 roots가 참조하지 않는 닿을 수 없는 오브젝트에 대해 가비지 콜렉션을 수행한다.

이 알고리즘은 위에서 설명한 참조-세기 알고리즘보다 효율적이다. 왜냐하면 "참조되지 않는 오브젝트"는 모두 "닿을 수 없는 오브젝트" 이지만 역은 성립하지 않기 때문이다. 즉, 순환 참조되어있으면 닿을 수 없지만, 참조되고 있기 때문이다.

2012년 기준으로 모든 최신 브라우저들은 가비지 콜렉션에서 Mark and Sweep 알고리즘을 사용한다. 지난 몇 년간 연구된 자바스크립트 가비지 콜렉션 알고리즘의 개선들은 모두 이 알고리즘에 대한 것이다. 개선된 알고리즘도 여전히 "더 이상 필요없는 오브젝트"를 "닿을 수 없는 오브젝트"로 정의하고 있다.

결론

  • 가비지 컬렉션은 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없다.

  • 객체는 도달 가능한 상태일 때 메모리에 남는다.

  • 참조세기 알고리즘은 참조 되는 개수를 세서 0개일 때 GC가 수집해가는 방식이다.

  • 참조된다고 해서 도달 가능한 것은 아니다. 서로 연결된 객체들도 도달 불가능할 수 있다. (순환 참조, 따라서 Mark and Sweep 을 사용.)

  • Mark and Sweep 방식은 roots 부터 참조 되는 객체들을 Mark 해가며 Mark 되지 않은 객체들을 Sweep(쓸어버리는)하는 방식이다.

참고
MDN 자바스크립트의 메모리관리
모던 자바스크립트 튜토리얼 가비지 컬렉션

profile
4년차 프론트엔드 개발자 문건우입니다.

0개의 댓글