객체 - 가비지 컬렉션

devheyrin·2022년 4월 20일
0

modern javascript

목록 보기
21/26
post-thumbnail

자바스크립트는 눈에 보이지 않는 곳에서 메모리 관리를 수행한다.

원시값, 객체, 함수 등 우리가 만드는 모든 것은 메모리를 차지한다. 그렇다면 더는 쓸모없어지게 된 것들은 어떻게 처리될까?

가비지 컬렉션 기준

자바스크립트는 도달 가능성이라는 개념을 사용해 메모리 관리를 수행한다.

‘도달 가능한' 값은 어떻게든 접근하거나 사용할 수 있는 값을 의미한다. 도달 가능한 값은 메모리에서 삭제되지 않는다.

  1. 아래 값들은 태생부터 도달이 가능하기 때문에, 명백한 이유 없이는 삭제되지 않는다. 이런 값은 루트라고 부른다.
    • 현재 함수의 지역 변수와 매개변수
    • 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
    • 전역 변수
  2. 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값은 도달 가능한 값이 된다. 전역 변수에 객체가 저장되어 있고, 이 객체의 프로퍼티가 또 다른 객체를 참조하고 있다면 프로퍼티가 참조하는 객체는 도달 가능한 값이 된다. 이 객체가 참조하는 다른 모든 것들도 도달 가능한 것으로 간주된다.

자바스크립트 엔진 내에서는 가비지 컬렉터가 끊임없이 동작하며 모든 객체를 모니터링하고, 도달할 수 없는 객체는 삭제한다.

예시

// user엔 객체 참조 값이 저장된다. 
let user = {
  name: "John"
};

그림에서 화살표는 객체 참조를 나타낸다. 전역 변수 user 는 {name: “John”} 이라는 객체를 참조하고 있다. 객체의 프로퍼티 name 은 원시값을 저장하고 있다.

user 의 값을 다른 값으로 덮어쓰면 화살표(참조) 가 사라진다.

user = null;

이제 객체는 도달할 수 없는 상태가 되었다. 객체에 접근할 방법도, 객체를 참조하는 것도 모두 사라졌으므로 가비지컬렉터는 객체에 내에 저장된 데이터를 삭제하고, 객체를 메모리에서 삭제한다.

참조 두 개

참조를 user 에서 admin 으로 복사하면 어떻게 될까?

let user = {
  name: "John"
};

let admin = user;

이 경우 둘 중 하나를 새로운 값으로 덮어써도 객체가 메모리에서 삭제되지 않는다. 그러나 참조 값을 저장하고 있는 변수 두 개가 모두 다른 값으로 덮어씌워진다면 객체는 메모리에서 삭제된다.

연결된 객체

함수 marry 는 매개변수로 받은 두 객체를 서로 참조하게 하면서 ‘결혼'시키고, 두 객체를 포함하는 새로운 객체를 반환한다.

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  }
}

let family = marry({
  name: "John"
}, {
  name: "Ann"
});

메모리 구조는 아래와 같이 나타낼 수 있다.

현재는 모든 객체가 도달 가능한 상태이다.

여기서 참조 두 개를 지운다.

delete family.father;
delete family.mother.husband;

“John” 객체에 대한 참조(들어오는 화살표)를 모두 지웠기 때문에, John 은 도달 가능한 상태가 아니게 된다. 따라서 메모리에서 제거된다. 객체 내에 저장된 프로퍼티 역시 메모리에서 제거된다.

제거 후 메모리 구조는 다음과 같다.

도달할 수 없는 섬

객체들이 연결되어 섬 같은 구조를 만들 때, 이 섬에 도달할 방법이 없는 경우 섬을 구성하는 객체 전부가 메모리에서 삭제된다.

family 가 아무것도 참조하지 않도록 만들었다. family 라는 이름으로 저장되어있는 주소값을 날려버리는 것과 같다.

family = null;

이제 메모리 내부 상태는 다음과 같아진다.

John 과 Ann 은 여전히 서로를 참조하고 있고, 외부에서 들어오는 참조 역시 갖고 있지만, 정작 이 객체를 가리키는 주소값이 사라졌기 때문에 객체와 루트의 연결이 사라지게 되고, 객체가 통째로 메모리에서 제거된다.

내부 알고리즘

가비지 컬렉션 기본 알고리즘은 mark-and-sweep 이라 부른다.

이 알고리즘은 대개 이러한 단계로 구성된다.

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

루트에 페인트를 들이붓는다고 상상해 보자. 루트를 시작으로 도달 가능한 객체 모두에는 페인트가 칠해지고, 페인트가 묻지 않는 객체는 메모리에서 삭제된다.

profile
개발자 헤이린 🔜 프로덕트 매니저로 나아가는 중!

0개의 댓글