자바스크립트 메모리 관리

katanazero·2020년 2월 19일
1

study-js

목록 보기
2/6
post-thumbnail

메모리 누수

  • 메모리 누수는 프로그램에서 할당된 메모리를 해제하지 못한 경우를 말함
    이로 인해, 성능이 떨어지고 간혹 프로그램 자체가 중단되기도 한다
    자바스크립트에서 GC(Garbage Colleltor)가 메모리를 올바른 방식으로 해제하지 않은 경우 발생한다

  • javascript GC가 사용하는 알고리즘은 mark-and-sweep 이다

javascript memory life cycle

1. 할당
2. 사용
3. 해제 -> GC 부분이 알아서 처리해 준다.

DOM 메모리 누수

  • DOM 엘리먼트를 가리키는 변수가 이벤트 콜백 외부에 선언된 경우 해당 DOM 항목을 제거하더라도 해당 항목은 여전히 메모리에 남게 된다.
let elements = {
  button: document.getElementById('button'),
  image: document.getElementById('image'),
  text: document.getElementById('text')
};

function removeButton() { // The button is a direct child of body. 
document.body.removeChild(elements.button); 
console.log(elements.button); 
// 여기서 elements 에서 여전히 button 참조를 가지고 있습니다. 
// 이 경우 button element는 여전히 메모리에 상주하게 되며 GC에 의해 수집될 수 없습니다. 
}

// 다른 예시

let one = document.getElementById('one');
let two = document.getElementById('two');

one.addEventListener('click', function() {
  two.remove();
  console.log(two); // 삭제 이후에도 html 을 출력할 것이다.
});
  • 해당 DOM이 HTML에서 사라지더라도 해당 DOM이 이벤트 콜백에서 사용됐다면 참조는 남는다.

window 전역 객체

  • 객체가 window 전역 객체에 포함되는 경우 해당 객체는 메모리에 존재하는 것
    모든 선언된 전역변수는 window 객체의 속성으로 설정될 수 있다는 점을 기억하자
function foo(arg) { 
  bar = "안녕 나는 바야?"; 
  // or
  this.tt = 'TT'; // 여기서 this 는 window 객체를 가리킨다.
}

var a = 'apple'; 
b = 'oranage'; // var 키워드가 없으면 암묵적으로 전역변수

console.log(window.a, window.b);
  • 가급적이면 전역변수를 피하는 것이 좋다(let, const 도 적극활용하면 더 좋을듯)

객체 참조 제한하기

  • 객체에 대한 모든 참조가 제거되면 해당 객체는 제거된다
    함수에 객체의 전체 범위가 아닌 필요한 범위(속성)만 전달해야 한다
// 안좋은 예시
let test = {name : 'zzz'};

function print(targetValue) {
	console.log(targetValue.name);
}

print(test);
  • 왜 안좋은 예시인건가?
    print() 함수는 실제로는 test.name 값만을 참조하면 되지만, name 속성을 접근하기 위해 test 객체 전체를 인자로 넘겼다. 이거는 print() 함수가 test 객체 전체를 함수 범위에 로딩해야 한다는 의미다.
// 개선된 예시
let test = {name : 'zzz'};

function print(targetValue) {
	console.log(targetValue);
}

print(test.name);

클로저(closures)

  • 클로저란 특정 실행 컨텍스트 생명주기가 끝났음에도 불구하고, 해당 실행 컨텍스트 스코프에
    접근이 가능한걸 의미한다.
    여기서 이야기하는 스코프는 변수를 접근하기 위한 범위(유효범위)이다
// 클로저 예제

function outer() {
  var outerValue = 100;
  
  function inner() {
    // 내부함수에서 외부함수 변수에 접근이 가능하다.
    // 내부 -> 외부로 검색하며(스코프 체이닝), 검색이 되면 해당 스코프에서 검색을 멈춘다.
    // 외부에서 내부는 검색 불가
    console.log(outerValue);
  }

  return inner; // 내부함수를 반환
}

var c = outer();
c();
console.dir(c);
  1. outer() 함수를 실행시킨다. (outer 함수에 실행컨텍스트가 생성이 된다)
  2. inner() 함수를 반환하고, otuer 함수는 종료된다.(outer 함수 실행컨텍스트가 사라짐)
  3. c(); 내부함수를 호출하낟
  4. 분명히 실행컨텍스트에서 정보가 사라졌을텐데, outerValue 100 이 정상적으로 출력이 된다.
  • 위와 같이 클로저를 남발하면, 참조가 되고 있기 때문에 GC에서는 언젠가 읽기/쓰기를 하겠구나 생각하여 메모리 해제를 하지 않는다
profile
developer life started : 2016.06.07 ~ 흔한 Front-end 개발자

0개의 댓글