[모던JS: Core] 가비지 컬렉션

KG·2021년 5월 9일
0

모던JS

목록 보기
4/47
post-thumbnail

Intro

본 포스팅은 여기에 올라온 게시글을 바탕으로 작성되었습니다.
파트와 카테고리 동일한 순서로 모든 내용을 소개하는 것이 아닌, 몰랐거나 새로운 내용 위주로 다시 정리하여 개인공부 목적으로 작성합니다.
중간중간 개인 판단 하에 필요하다고 생각될 시, 기존 내용에 추가로 보충되는 내용이 있을 수 있습니다.

Garbage Collection

자바스크립트는 일일이 사용이 끝난 값은 할당을 해제하고 사용할 값은 할당하는 등의 메모리를 직접 관리할 필요가 없다. 자바스크립트 엔진 내에서 가비지 컬렉터(Garbage Collector)가 끊임없이 동작하며 메모리와 관련된 최적화를 수행해준다.

원시값, 객체, 함수 등 자바스크립트로 구현하는 모든 값은 어느 시점에 결국 메모리의 특정 공간을 차지한다. 해당 값의 사용이 끝났거나, 쓸모없어진 경우에도 이 값들을 계속 점유하도록 놔둔다면 메모리의 사용량이 매우 늘어나고, 새로운 값을 할당하기 위한 자리가 부족할 수도 있다.

따라서 가비지 컬렉터는 쓸모 없어진 값들을 검사하여 메모리로부터 할당을 해제하는 작업을 알아서 수행한다. 이때 자바스크립트는 도달 가능성(Reachability)라는 개념을 사용해 메모리 관리를 수행한다.

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

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

위 목록은 태생부터 항상 도달 가능성이 보장되기 때문에 명백한 이유가 없다면 가비지 컬렉터에 의해 제거되지 않는다. 이러한 값들을 보통 루트(root)라고 칭한다.

또한 이러한 루트가 참조하는 값 또는 체이닝으로 루트에서 참조할 수 있는 모든 값들 역시 도달 가능한 값이 된다. 때문에 이러한 참조가 루트에 연결되어 있다면 이 역시 제거되지 않는다.

가령 아래 이미지와 같은 객체가 생성되있다고 가정하자.

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;

아직 husband 였던 객체에서 mother 객체를 wife로 참조할 수 있지만 제일 중요한건 루트(global)에서는 해당 객체를 참조할 수 없다는 점이다. 즉 도달 가능한 상태가 아니므로 제거된다.

Mark and Sweep

자바스크립트 엔진에서 가비지 컬렉터가 수행하는 내부 알고리즘을 mark-and-sweep이라고 한다. 도달 가능한 객체를 마크(mark)하고 그 외의 값은 제거(sweep)하는 개념이다. 이 과정은 그래프 탐색 알고리즘인 DFS와 상당히 유사하다. 루트값으로부터 출발하여 방문할 수 있는 모든 값들을 방문하며 마킹하고, 마킹이 되지 않는 값들은 도달할 수 없는 값으로 판단하여 제거한다. 위 과정을 그림으로 나타내면 아래와 같다. 빨간 테두리는 도달이 불가능 하기때문에 가비지 컬렉터에 의해 제거된다.

자바스크립트 엔진은 최대한 실행에 영향을 적게 미치기 위해 다양한 최적화 기법을 적용한다. 이에 대한 간단한 설명은 다음과 같다.

  1. generation collection(세대별 수집)
    • 객체를 새로운 객체와 오래된 객체로 구분.
    • 객체 상당수는 생성 후 제 역할을 다하고 빠르게 쓸모가 없어짐. 이러한 객체를 새로운 객체로 판단
    • 새로운 객체는 매우 적극적으로 가비지 컬렉션을 통해 메모리에서 제거
    • 오래된 객체는 상대적으로 덜 감시
  1. incremental collection(점진적 수집)

    • 방문할 객체가 많을 수록 탐색 시간에 오래 소요
    • 가비지 컬렉션이 오래 걸리면 실행 속도 역시 저하
    • 따라서 가비지 컬렉션을 여러 부분으로 분리 후 별도 수행
  2. idle-time collection(유휴 시간 수집)

    • 실행 시간에 영향 최소화를 위해 CPU가 쉬고 있을 상태(유휴 상태)일 때에만 가비지 컬렉션 수행

가비지 컬렉션의 동작 방식은 브라우저의 자바스크립트 엔진에 따라 모두 상이하다. 그러나 2012년 기준으로 모든 최신 브라우저들은 가비지 컬렉션에서 mark-and-sweep 알고리즘을 사용하는 것으로 알려져있다.

자바스크립트는 동적 언어 이면서 메모리 관리 역시 자동으로 수행되는데, 아직 명시적으로 또는 프로그래밍 방식으로 가비지 컬렉션을 작동할 수 있는 방법은 없다고 한다.

References

  1. https://ko.javascript.info/garbage-collection
  2. https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management
  3. https://engineering.huiseoul.com/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%91%EB%8F%99%ED%95%98%EB%8A%94%EA%B0%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC-4%EA%B0%80%EC%A7%80-%ED%9D%94%ED%95%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98-%EB%8C%80%EC%B2%98%EB%B2%95-5b0d217d788d
profile
개발잘하고싶다

0개의 댓글