자바스크립트로 하는 자료구조와 알고리즘 - 7장

profile image pIutos 2022. 7. 15. 14:48

7장. 자바스크립트 메모리 관리

메모리 누수

자바스크립트는 타언어와는 달리 프로그래머가 직접 메모리를 수동으로 할당하고 해제하지 않고 사용하지않는 변수, 즉 메모리를 삭제해주는 가비지 컬렉터가 있기 때문에 매니지드언어라고 부른다. 하지만 이러한 기능에도 메모리가 올바른 방식으로 해제되지 않아 메모리 누수가 발생할 수 있기 때문에 이를 피하기위한 여러 방법이 존재한다.

객체에 대한 참조

var foo = {
	bar1: memory(), // 5kb
    bar2: memory(), // 5kb
}

function clickEvent() {
	alert(foo.bar1[0]);
}

객체에 대한 참조가 있다면 해당 참조는 메모리에 존재하는 것이다. foo객체가 bar1만을 참조하더라도 foo객체 전체를 clickEvent() 함수의 범위에 로딩해야 하기 때문에 실제로는 5KB가 아니라, 10KB의 메모리를 사용한다.

DOM 메모리 누수

DOM 항목을 가리키는 변수가 이벤트 콜백 외부에 선언된 경우 해당 DOM 항목을 제거하더라도 해당 항목은 여전히 메모리에 남게된다.

var one = document.getElementById("one");
var two = document.getElementById("two");

one.addEventListner('click', function() {
    two.remove();
    console.log(two); // 삭제 후에도 html을 출력한다(참조 유지)
}

위 코드에서 웹페이지의 two항목은 사라지지만, 해당 DOM이 HTML에서 사라지더라도 해당 DOM이 이벤트 콜백에서 사용되었다면 참조는 남는다. 이렇게 two 항목이 더 이상 사용중이 아닌경우를 '메모리 누수'라 부르며 미리 누수를 피해야한다. 따라서 아래와 같은 코드를 작성할 수 있다.

var one = document.getElementById("one");

one.addEventListner('click', function() {
    var two = document.getElementById("two"); // DOM항목을 이벤트 콜백 내부에서 사용한다.
    two.remove();
}
one.removeEventListner('click', function () {
    one.addEventListener('click', callBackExample);
}); // 또는 클릭 핸들러를 사용한 뒤 등록 해지하는 방법도 있다.

window 전역 객체

객체가 window 전역 객체에 포함되는 경우 해당 객체는 메모리에 존재하는 것이고, window의 속성으로 선언된 추가적인 객체는 모두 제거할 수 없다. window는 브라우저가 실행하는데 필요한 객체이기 때문이다. 따라서 가능하면 전역변수는 사용하지 않는 것이 좋다.

객체 참조 제한하기

객체에 대한 모든 참조가 제거되면 해당 객체는 제거되기 때문에 함수에는 객체의 전체범위가 아닌 필요한 범위, 속성만 전달해야한다.

var test = { prop1: 'test' };

function printProp(test) {
    console.log(test.prop1); // x
    console.log(test) // o
}

printProp(test); // x
printProp(test.prop1); // o

delete 연산자

원치 않는 객체 속성을 제거하기 위해 delete 연산자를 사용할 수 있다. 이때 delete 연산자는 객체에서만 동작한다.

var test = { prop1: 'test' };

console.log(test.prop1); // test

delete test.prop1;

console.log(test.prop1); // undefined