가비지 컬렉션 파트 링크 : https://ko.javascript.info/garbage-collection
원시값, 객체, 함수 등 우리가 만드는 모든 것은 메모리를 차지한다.
더이상 쓰지 않을 것들은 자바스크립트가 메모리 관리를 통해 찾아내서 삭제한다.
자바스크립트는 도달 가능성(reachability) 이라는 개념을 사용해 메모리 관리를 수행한다.
도달 가능한 값 : 어떻게든 접근하거나 사용할 수 있는 값을 의미.
도달 가능한 값은 메모리에서 삭제되지 않는다.
아래는 생성될 때부터 당연히 도달 가능하기 때문에 명백한 이유 없이는 삭제되지 않는 값들이다.
(콜론 뒤에 나오는 이유들은 삭제되지 않는 이유에 대한 주관적인 추측을 적었다.)
1) 현재 함수의 지역 변수와 매개변수
: 함수가 동작하면서 사용할 변수들이기 때문에 삭제되면 안되는 값들이다.
2) 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
: 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수는 스코프 상 함수가 필수적으로 접근하여 사용하게 될 변수들이므로 삭제되면 안되는 값들이다.
3) 전역 변수 등
: 전역 변수는 보통 한 곳에서만 쓰이지 않고 여러곳에서 쓰이는 값들이다. 전역 변수가 삭제되면 곳곳에서 해당 값을 사용하지 못해 에러가 발생할 수 있다.
위에서 설명한 값들은 루트(root)라고 부른다.
루트가 참조하거나 체이닝으로 루트에서 참조할 수 있는 값들은 도달 가능한 값이 된다.
자바스크립트 엔진 내에서는 "가비지 컬렉터(garbage collector)"가 끊임없이 동작하면서 모든 객체를 모니터링하고 도달할 수 없는 객체는 삭제한다.
가비지 컬렉터 작동 예시
<script>
let user = {
name: "John"
}
</script>
<script>
let user = {
name: "John"
}
user = null;
</script>
user의 값을 다른 값으로 덮어쓰면 기존에 갖고 있던 { name: "John" }에 대한 참조 값이 사라진다.
이렇게 되면 { name: "John" }에 대한 참조 값이 사라져 해당 객체는 접근할 수 없는(접근할 수 있는 참조 값이 없는 상태) '도달할 수 없는 값'이 된다.
가비지 컬렉터는 도달할 수 없는 값이 된 { name: "John" }에 저장된 데이터(name : "John")를 삭제하고 { name: "John" } 객체를 메모리에서 삭제한다.
<script>
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
fathrer: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
})
</script>
위 예시를 실행하면 family객체는 아래와 같은 값을 반환한다.
<script>
father = {
name: "John",
wife: {name: "Ann"}
}
mother = {
name: "Ann",
husband: {name: "John"}
}
</script>
이 상태에서 delete family.father;
명령어를 실행하여 family의 father 객체와 mother객체의 husband 프로퍼티를 삭제하면 John이라는 값에 도달할 수 있는 참조값이 사라진다.
delete family.mother.husband;
따라서 도달할 수 없는 값이 된 John객체({name: "John"})는 메모리에서 삭제되고 name 프로퍼티 또한 메모리에서 삭제된다.
객체들이 참조값으로 서로 연결되어 섬 같은 구조를 만드는데, 이 섬에 도달할 방법이 없는 경우, 섬을 구성하는 객체 전부가 메모리에서 삭제된다.
예를 들어 근원 객체인 family가 아무것도 참조하지 않을 경우 (family = null
) family 아래에 father, mother 객체가 서로를 온전히 참조하고 있어도 루트 객체인 family 를 참조하는 값이 없으므로 섬(family와 family 아래의 객체들) 전체가 도달할 수 없는 값이 되고 섬을 구성하는 모든 객체들이 메모리에서 삭제된다.
mark-and-sweep 이라는 가비지 콜렉션 기본 알고리즘을 살펴보자.
'가비지 컬렉션’은 대개 아래 단계를 거쳐 수행된다.
루트 정보를 mark(기억) => 루트가 참조하는 객체를 방문, mark => mark된 모든 객체에 방문, 그 객체들이 참조하는 객체도 mark. (한 번 방문한 객체는 전부 mark 하기 때문에 중복 방문 없음) => 루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정 반복 => mark 되지 않은 모든 객체를 메모리에서 삭제
위에서 본 알고리즘은 가장 기본적인 알고리즘이고 자바스크립트 엔진마다 가비지 콜렉션 최적화 기법이 달라지므로 호기심에 의한 학습 정도로만 추천한다고 한다.