본문 바로가기
JavaScript 심화 시리즈

[JavaScript 심화 시리즈] 7일차: JavaScript 메모리 관리와 성능 최적화 이해하기

by cogito21_js 2024. 8. 7.
반응형

7. 메모리 관리와 성능 최적화

메모리 관리란 무엇인가?

메모리 관리는 프로그램이 실행될 때 사용되는 메모리의 할당과 해제를 의미합니다. JavaScript는 자동 메모리 관리 기능을 제공하지만, 메모리 누수를 방지하고 성능을 최적화하기 위해 메모리 사용에 주의를 기울이는 것이 중요합니다.

가비지 컬렉션

JavaScript는 자동으로 메모리를 관리하기 위해 가비지 컬렉터(Garbage Collector)를 사용합니다. 가비지 컬렉션은 더 이상 참조되지 않는 객체를 메모리에서 해제합니다.

1. 참조 카운팅

객체가 얼마나 많은 참조를 받고 있는지를 추적합니다. 참조 카운트가 0이 되면 객체는 가비지 컬렉션 대상이 됩니다.

2. 마크 앤 스윕

객체 그래프를 탐색하여 도달할 수 없는 객체를 마크하고, 마크되지 않은 객체를 해제합니다.

메모리 누수

메모리 누수는 더 이상 필요하지 않은 메모리가 해제되지 않고 남아 있는 현상입니다. 이는 프로그램의 성능 저하를 초래할 수 있습니다.

1. 전역 변수 사용

전역 변수를 너무 많이 사용하면 메모리 누수가 발생할 수 있습니다.

var globalVar = "I am a global variable"; // 가급적 사용을 피합니다.

2. 클로저 사용

클로저는 메모리 누수의 원인이 될 수 있습니다. 필요하지 않은 클로저는 즉시 해제해야 합니다.

function createFunction() {
  let localVar = "I am a local variable";

  return function() {
    console.log(localVar);
  };
}

let myFunction = createFunction();
myFunction = null; // 메모리 해제

3. 이벤트 리스너

이벤트 리스너를 등록한 후 제거하지 않으면 메모리 누수가 발생할 수 있습니다.

let element = document.getElementById('myElement');

function handleClick() {
  console.log('Element clicked');
}

element.addEventListener('click', handleClick);
element.removeEventListener('click', handleClick); // 이벤트 리스너 제거

성능 최적화

JavaScript의 성능을 최적화하기 위해 몇 가지 중요한 기술을 알아봅시다.

1. 반복문 최적화

반복문 내에서 불필요한 연산을 피하고, 루프의 길이를 변수에 저장하여 사용합니다.

let items = [1, 2, 3, 4, 5];
let length = items.length;

for (let i = 0; i < length; i++) {
  console.log(items[i]);
}

2. DOM 조작 최소화

DOM 조작은 비용이 많이 드는 작업입니다. 가능한 한 DOM 조작을 최소화하고, 배치하여 처리합니다.

let fragment = document.createDocumentFragment();

for (let i = 0; i < 100; i++) {
  let div = document.createElement('div');
  div.textContent = 'This is div ' + i;
  fragment.appendChild(div);
}

document.body.appendChild(fragment);

3. 디바운싱과 스로틀링

이벤트 핸들러의 호출 빈도를 줄이기 위해 디바운싱(Debouncing)과 스로틀링(Throttling)을 사용합니다.

디바운싱 예제:

function debounce(func, delay) {
  let debounceTimer;
  return function() {
    const context = this;
    const args = arguments;
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => func.apply(context, args), delay);
  };
}

window.addEventListener('resize', debounce(function() {
  console.log('Window resized');
}, 200));

스로틀링 예제:

function throttle(func, limit) {
  let lastFunc;
  let lastRan;
  return function() {
    const context = this;
    const args = arguments;
    if (!lastRan) {
      func.apply(context, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function() {
        if ((Date.now() - lastRan) >= limit) {
          func.apply(context, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  };
}

window.addEventListener('scroll', throttle(function() {
  console.log('Window scrolled');
}, 200));

결론

JavaScript의 메모리 관리와 성능 최적화는 코드의 효율성과 안정성을 높이는 데 매우 중요합니다. 가비지 컬렉션의 작동 원리를 이해하고, 메모리 누수를 방지하며, 성능 최적화 기법을 사용하여 더욱 나은 프로그램을 작성할 수 있습니다.

이로써 JavaScript 심화 시리즈를 마치게 되었습니다. 이 시리즈를 통해 JavaScript의 다양한 심화 개념을 이해하고, 이를 실제 코드에 적용할 수 있기를 바랍니다.

반응형