-
자바스크립트 메모리 관리 [가비지 컬렉션] :: 마이구미Javascript 2016. 7. 12. 21:56반응형
이번 글은 자바스크립트의 메모리 관리에 대해 알아볼 것이다.
C를 사용해 봤다면
malloc()
과free() 사용했을 것이다.
예를 들어 무언가를 생성하고 메모리를 할당하고 필요없어지면 메모리에서 없애버리기 위해 사용한다.
이렇게 C나 C++은 메모리를 직접 할당하고 해제하여야한다.
그에 반해 자바는 GC라는 녀석이 자동으로 메모리를 관리해주고 있다.
이 GC가 가비지 콜렉션(Garbage Collection)이다. 이것은 C와 JAVA의 큰 차이 중 하나이다.
자바스크립트 또한 자바처럼 GC를 통해 메모리를 관리한다.
다시 한번 말하자면 C나 C++은 소스를 통해 메모리를 직접 할당하고 직접 해제하여야한다.
그에 반해 자바나 자바스크립트와 같은 고급 언어들은 GC라는 녀석이 알아서 필요없으면 메모리를 해제하여 관리를 해준다.
즉, 가비지 콜렉터란 메모리 할당을 추적하고 할당된 메모리가 더 이상 필요 없어졌을 때 해제하는 작업을 한다.
자바스크립트의 GC는 익스플로러 6,7까지 Reference-counting 알고리즘을 사용하였고,
이후 Mark-and-sweep 알고리즘을 사용하였다.
먼저 Reference-counting 알고리즘을 알아보자.
이 알고리즘은 "더 이상 필요없는 오브젝트"를 "어떤 다른 오브젝트도 참조하지 않는 오브젝트"라고 정의한다. 어떤 오브젝트를 참조하는 다른 오브젝트가 하나도 없다면 그 오브젝트에 대해 가비지 콜렉션을 수행한다.
예제를 보자.
var obj = { a: { b:2 } }
보시다시피 { a: { b:2 } } 객체와 { b:2 } 객체 2개를 생성했다.{ a: { b:2 } } 객체는 obj라는 변수에 할당하였고, { b:2 } 객체는 속성으로 참조되었다.여기서 위 정의와 같이 GC가 수행될 메모리는 존재하지 않는다.var obj2 = obj;
변수 obj2 에 obj를 할당하였다.
현재 { a: { b:2 } } 객체를 참조하는 변수는 obj, obj2가 되었다.
var obj = 1;
변수 obj에 1을 할당하여도 { a: { b:2 } } 객체를 참조하는 변수는 obj2가 있기에,
여기서도 또한 GC가 수행될 메모리는 존재하지 않는다.
var obj3 = obj2.a;
변수 obj3에 { b:2 } 객체를 할당하였다.
obj2.a를 참조하는 변수는 obj2와 obj3가 되었다.
var obj2 = 1;
변수 obj2에 1을 할당하여 유일하게 obj의 있던 객체를 참조하는 변수는 사라졌다.
그렇다면 GC가 수행되어야한다.
하지만 obj 객체에 있던 a 속성이 변수 obj3에 의해 참조되고 있으므로 GC는 수행되지 않는다.
var obj3 = 1;
변수 obj3 마저 1을 할당함으로써 이제 obj 객체를 참조하는 것이 없으므로 GC가 수행되어진다.
위와 같은 설명으로 보면 아무 문제 없다.
근데 왜 Reference-counting에서 Mark-and-sweep로 개선되었을까?
그 이유는 다음과 같은 순환 참조의 경우이다.
function f() {
var o = {};
var o2 = {};
o.a = o2; // o는 o2를 참조한다.
o2.a = o; // o2는 o를 참조한다.
return "azerty";
}
f();
위와 같은 경우 f() 함수가 호출되어지면 o, o2 객체는 아무 의미가 없어지기 때문에
GC가 수행되어 메모리를 해제해줘야한다.
하지만 서로 참조를 하고 있는 상황이기 때문에 GC가 수행되지 않는 문제점이 발생했다.
그리하여 Mark-and-sweep 알고리즘으로 개선되었다.
이 알고리즘은 "더 이상 필요없는 오브젝트"를 "닿을 수 없는 오브젝트"로 정의한다.
이 알고리즘은 roots 라는 오브젝트의 집합을 가지고 있다(자바스크립트에서는 전역 변수들을 의미한다). 주기적으로 가비지 콜렉터는 roots로 부터 시작하여 roots가 참조하는 오브젝트들, roots가 참조하는 오브젝트가 참조하는 오브젝트들... 을 닿을 수 있는 오브젝트라고 표시한다. 그리고 닿을 수 있는 오브젝트가 아닌 닿을 수 없는 오브젝트에 대해 가비지 콜렉션을 수행한다.
정의대로 순환 참조가 일어났다고해도 roots로 인해 오브젝트가 닿을 수 없다면 GC가 수행된다.
이로써 순환 참조의 문제는 발생되지 않는다.
더욱 더 깊은 내용이 많지만 더 깊게는 잘 모르겠다..
다음에 기회가 된다면 정리 후 글을 작성하겠다.
관련 자료
https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management
반응형'Javascript' 카테고리의 다른 글
자바스크립트 즉시실행함수 :: 마이구미 (0) 2016.07.25 || , && 연산자 사용법 [javascript] :: 마이구미 (5) 2016.07.24 자바스크립트 메모리 누수 :: 마이구미 (0) 2016.07.13 이벤트 해제 unbind 활용 [jQuery] :: 마이구미 (2) 2016.07.03 자바스크립트 Promise 동기 프로그래밍 : 마이구미 (0) 2016.06.09