무브라더

[JavaScript] 가비지콜렉션, WeakRef 본문

Programming/JavaScript

[JavaScript] 가비지콜렉션, WeakRef

동스다
반응형
SMALL

몇달 전에 나온 ES2021 문법에서 자바스크립트에서도 약한 참조라는 개념이 등장했다고 한다.

 

이는 가비지콜렉션(Gabage Collection) 과 관련이 있는데 가바지 콜렉션이란 과연 뭘까?

 

해석을 해보면 '쓰레기수집' 이다. 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서

필요없게 된 영역을 해제하는 기능이다

 

C를 예로 들면 free()라는 함수로 직접 메모리를 해제해줘야하지만, Java 개발자들은 메모리를 직접 해제해주는 일이 없었을텐데 이는 JVM의 가비지 컬렉터가 불필요한 메모리를 알아서 정리해주기 때문이다.

 

대신 자바에서는 불필요한 데이터를 표한하기 위해 일반적으로 null 을 선언해준다. 

 

Number num = new Nmuber();
num.setNumber(1000);
num = null;

// 가비지 발생
num = new Number();
num.setNumber(1000);

1000 으로 생성된 num 객체는 더 이상 사용되지 않고 참조 되지 않아 말 그대로 Gabage(쓰레기) 가 되었다.

메모리 누수를 막기 위해 가비지컬렉터를 주기적으로 검사하여 (자동으로) Java 에서는 메모리를 청소해준다.

(System.gc() 를 이용해 호출 할 수 있지만, 해당 메소드를 호출하는 것은 시스템 성능에 매우 큰 영향을 주므로 절대 해선 안되는 행위다)

 

그렇다면 본론으로 넘어가서 ES2021에 나온 자바스크립트의 문법으로 이런 가비지데이터를 어떻게 관리해주는지 살펴보자. 

 

약한 참조를 위한 WeakRefs

 

일반적으로 자바스크립트에서 객체의 참조는 강하게 유지된다. 즉 객체에 대한 참조가 있는 한 가비지 컬렉션이 일어나지 않는다는 것이다.

const num = { x : 10 , y : 20 };
// num 에 접근할 수 있는 한 가비지 컬렉션 발생x

그렇다면 이렇게 강하게 유지되는 참조를 약하게 사용하기 위해 나온 문법이 WeakRefs 이다.

 

필요 없게 된 용량의 정보를 꼐속 메모리상에 들고 있으면 메모리 누수가 일어날테고 작던 크던 프로그램에 영향을 끼칠 수 있다. 하지만 객체가 약한 참조로 참조되고 있다면 아무도 모르는 것과 동일하게 언젠가는 사라질 수 있다.

 

 

참고예제 ) https://blog.shiren.dev/2021-08-30/

const map = new Map();
const obj = { data : new Array(10000).join('*')};

map.set('someData', obj);

setInterval( () = > {
	console.log(map.get('someData').data);
}, 1000 );

위 코드에서 obj.data 로 참조하고 있는 1만개의 배열은 일반적인 자바스크립트의 참조 형태인 강한 참조이기 때문에

배열이 가비지 컬렉션 되서 메모리상에서 사라지는 경우가 절대 없다.

 

setInterval 에 전달된 콜백에 의해 클로저가 만들어지고 클로저에서는 map을 참조하고 있고 map은 obj가 참조했던 객체를 참조하기 때문에 콜백이 실행될 때마다 데이터의 존재가 보장된다.

 

위 코드에서 WeakRef를 적용해 obj가 참조하고 있는 객체가 가비지컬렉션 대상에서 제거 될 수 있도록 바꿔보겠다.

const map = new Map();

const obj = {data: new Array(10000).join('*')};

map.set('someData', new WeakRef(obj));

setInterval(() => {
    console.log(map.get('someData').deref().data);
 }, 1000);

바뀐부분은 obj -> new WeakRef(obj) , get('someData').data -> get('someData').deref().data이다.

 

WeakRef 의 실체는 약한 참조를 만드는 객체의 생성자였다! new 키워드와 함께 사용하며 WeakRef의 메소드인 deref() 를 사용해 참조하는 대상에 접근 할 수 있다. 참조하는 대상이 가비지 컬렉션 됐다면 deref()는 undefined를 리턴한다.

 

시간이 조금만 흐르면 약한 참조의 객체가 가비지컬렉터에 의해 잡아 먹히며 setInterval의 콜백은 더 이상 객체의 존재를 보장받지 못한다. (가비지 컬렉션의 구현에 따라 브라우저별로 객체의 제거되는 시점은 다를 수 있다.)

 

전역에서 실행하는 경우에는 obj가 전역에 계속 상주하며 강한 참조를 가지고 있기 때문에 객체가 사라지지는 않는다.

 

전역에서 확인하고 싶으면 map.set 이후 obj에  null이나 다른 값을 할당하면 된다.

 

다음 포스팅은 가비지 컬렉트가 되는 시점을 알 수 있는 Finalizers 에 대해 알아보도록 하겠다.

반응형
LIST

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

[JavaScript] Array.from  (0) 2022.03.25
[JavaScript] 클로저 정리  (0) 2022.03.25
[JavaScript] '?' 옵셔널 체이닝 연산자  (0) 2022.03.24
[JavaScript] prototype 정리  (0) 2022.03.24
[ES6] const, let, var 차이점 알아보기  (0) 2022.03.02
Comments