C언어 같은 저수준의 언어와 달리 자바스크립트는 객체가 생성되었을 때 자동으로 메모리를 할당하고 쓸모 없어졌을 때 "자동으로" 해제한다.
메모리 생존주기는 프로그래밍 언어와 관계없이 다음과 비슷하다.
const n=123;
const obj={
a:1,
b:null
};
const day=new Date();
const s='nomaroma';
const s2=s.substr(0,3);
값 사용(읽기, 쓰기)
기본적으로는 할당된 메모리를 읽고 쓰는 것을 의미.
할당된 메모리가 더이상 필요없어지면 해제
자바스크립트는 가비지 컬렉션(GC)라는 자동 메모리 관리 방법을 사용한다.
메모리 관리 방법 중 하나로, 시스템에서 더이상 사용하지 않는 메모리 블럭을 찾아 자동으로 다시 사용 가능한 자원으로 회수하는 것이다.
가비지 컬렉터: 시스템에서 가비지 컬렉션을 수행하는 프로그램
가비지 컬렉터의 목적: 메모리 할당을 추척하고 할당된 메모리 블럭이 더 이상 필요하지 않게 되었는지를 판단하여 회수하는 것이다.
여기서 "더 이상 필요하지 않는" 메모리를 찾는데 사용되는 알고리즘은 참조-세기(Reference-Counting)와 표시하고-쓸기(Mark-and-Sweep)로 두 가지가 있다.
참고 | 참조(Reference)
A라는 메모리를 통해 B라는 메모리에 접근할 수 있으면, "B는 A에 참조된다"라고 한다.
앞으로 쓰일 "오브젝트"라는 어휘의 의미는 자바스크립트 오브젝트 뿐만 아니라 함수 스코프도 포괄한다.
참조-세기 알고리즘은 "더 이상 필요없는 오브젝트"를 "어떤 다른 오브젝트도 참조하지 않는 오브젝트"라고 정의한다. 이 오브젝트를 "가비지"라고 부르고, 가비지를 참조하는 다른 오브젝트가 하나도 없는 경우 메모리를 수집한다.
이 알고리즘은 단순하지만, 순환 참조를 다루는 일에 한계가 있다.
function f(){
const x={};
const y={};
x.a=y; //x는 y를 참조
y.a=x; //y는 x를 참조
return "hello, world";
}
f();
위 예제에서 두 객체가 서로 참조하는 속성으로 생성되어 순환 구조를 가지게 된다.
함수 호출이 완료되면 이 두 객체는 스코프를 벗어나게 되며, 그 시점에서 두 객체는 불필요해지므로 할당되었던 메모리를 회수해야 한다. 하지만 두 객체가 서로를 참조하고 있으므로, 참조-세기 알고리즘으로는 두 객체 모두 가비지 컬렉션의 대상으로 판단하지 않는다.
따라서 해당 알고리즘으로는 메모리 누수가 발생하게 된다.
이 알고리즘은 "더 이상 필요없는 오브젝트"를 "닿을 수 없는 오브젝트"로 정의한다.
이 알고리즘은 roots라는 오브젝트의 집합을 가지고 있다(자바스크립트에서는 전역변수들을 의미). 주기적으로 가비지 컬렉터는 roots로부터 시작하여 roots가 참조하는 오브젝트들, roots가 참조하는 오브젝트가 참조하는 오브젝트들..을 닿을 수 있는 오브젝트라고 표시한다.
그리고 닿을 수 없는 오브젝트에 대해 가비지 컬렉션을 수행한다.
이 알고리즘은 참조-세기 알고리즘보다 효율적이다. 왜냐하면 "참조되지 않는 오브젝트"는 모두 "닿을 수 없는 오브젝트"이지만 역은 성립하지 않기 때문이다.
따라서 함수가 리턴되어 함수 내부의 오브젝트들에 닿을 수 없어졌을 때도, 순환 참조가 일어났을 때도 roots로부터 접근이 불가능해지면 가비지 컬렉션이 일어나게 된다.
모든 최신 브라우저들은 가비지 컬렉션에 표시하고-쓸기(Mark-and-Sweep) 알고리즘을 사용한다.
+한계점: 자바스크립트는 명시적으로 또는 프로그래밍 방식으로(수동으로) 가비지 컬렉션을 작동할 수 없다. (2019년 기준)
https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management