[JavaScript] 가비지 컬렉션

2020. 8. 17. 14:48Programming Languages/JavaScript

자바스크립트는 눈에 보이지 않는 곳에서 메모리 관리를 수행합니다. 원시값, 함수, 객체 등 우리가 만들고 사용하는 모든 것은 메모리를 차지합니다. 그렇다면 사용하지 않는 것들은 어떻게 될까요?

 

가비지 컬렉션 기준

자바스크립트는 도달 가능성(reachability) 이라는 개념을 사용해 메모리 관리를 수행합니다. 도달할 수 있는 값은 쉽게 말해 어떻게든 접근하거나 사용할 수 있는 값을 의미합니다. 도달할 수 있는 값은 메모리에 계속 존재합니다. 아래 나오는 값들은 만들어질 때부터 도달 가능하기 때문에, 특별한 이유없이 삭제되지 않습니다.

 

  • 현재 함수의 지역 변수와 매개변수
  • 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
  • 전역 변수
  • 기타

이런 값은 루트(root) 라고 부릅니다.

또한 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값은 도달 가능한 값이 됩니다.

 

자바스크립트 엔진 내에서는 가비지 컬렉터가 끊임없이 동작합니다. 가비지 컬렉터는 모든 객체를 보고 있고, 도달할 수 없는 객체는 삭제합니다. 자바와 비슷한 면이네요. 

 

예시를 한 번 봅시다.

let user = {
  name: "Loopy",
}

위 예제를 그림으로 표현해보면 아래와 같습니다.

 

이 그림에서 화살표는 객체 참조를 나타냅니다. user를 원시값으로 덮어쓰면 화살표(참조)가 사라집니다.

여기서 user의 값을 null로 바꾼다면 어떻게 될까요?

 

객체에 대한 참조가 사라지고 user는 null로 덮어씌여집니다.

그리고 연결이 끊긴 객체는 우주 속 먼지가 되어 사라집니다...

 

2개 이상의 변수가 한 객체를 가리키고 있을 때도 마찬가지입니다. 가리키고 있는 변수가 모두 가리키고 있던 객체를 가리키지 않게 되면 그 객체는 가비지 컬렉터가 수거해가고 사라져버립니다.

 

도달할 수 없는 섬

객체들이 연결되어 섬 같은 구조를 만드는데, 이 섬에 도달할 방법이 없는 경우, 섬을 구성하는 객체 전부가 메모리에서 삭제됩니다. 아래 가족관계 예제를 봅시다.

 

전역 변수 family는 mother와 father라는 객체를 가리키는 참조값을 가집니다. 그리고 mother 객체와 father 객체는 각각 name 이라는 프로퍼티를 가지고 있고, 서로의 참조값을 husband와 wife로 가집니다.

여기서 family의 값을 null로 덮어씌우면 어떻게 될까요?

 

 

상자로 둘러쌓인 객체들 모두가 메모리에서 삭제됩니다. 어렵지 않죠?

 

내부 알고리즘

가비지 컬렉션은  'mark-and-sweep'이라고 불리는 알고리즘을 기본으로 동작합니다. 한 번 단계별로 살펴봅시다.

  1. 가비지 컬렉터는 루트(root) 정보를 수집하고 이를 mark(기억)합니다.
  2. 루트가 참조하고 있는 모든 객체를 방문하고 이것들을 mark합니다.
  3. mark 된 모든 객체에 방문하고 그 객체들이 참조하는 객체도 mark 합니다. 한 번 방문한 객체는 모두 mark하기 때문에 같은 객체를 방문하는 일은 없습니다.
  4. 루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복합니다.
  5. mark되지 않은 모든 객체를 메모리에서 삭제합니다.

그림으로 보겠습니다. 순서대로입니다.

 

 

 

 

위에서부터 페인트를 붇는다고 생각하면 이해가 쉽습니다. 맨 위에서부터 페인트를 부으면 결국 연결돼있는 곳에는 모두 페인트가 들어갈 것이고, 연결돼있지 않은 곳에는 페인트가 들어가지 않습니다. 가비지 컬렉터는 페인트가 없는 곳들을 수집해서 삭제한다고 생각하면 됩니다. 이 외에도 다양한 알고리즘이 있습니다. 관심이 있으신 분들은 찾아보시길 바랍니다. 

'Programming Languages > JavaScript' 카테고리의 다른 글

[JavaScript] Promise Error Handling  (0) 2021.05.12
[JavaScript] Promise  (0) 2021.05.12
[JavaScript] 객체 복사  (0) 2020.08.12
[JavaScript] 객체  (0) 2020.08.11
[JavaScript] Prototype  (0) 2020.08.02