본문 바로가기
프로그래밍/JavaScript

JavaScript에서 효율적인 메모리 관리를 위한 비밀 팁

by 꾸션 2023. 4. 4.

JavaScript는 가비지 수집기가 내부적으로 구현되어 있어서, 메모리 관리를 개발자가 직접 수행하지 않아도 됩니다. 하지만, 개발자가 이를 무시하면 코드에서 메모리 누수가 발생할 수 있습니다. 이러한 메모리 누수는 성능 저하, 사용자 경험 저하, 심지어 서비스 장애로 이어질 수 있습니다.

 

자바스크립트 메모리 관리 팁

 

따라서 이번 글에서는 JavaScript에서 효율적인 메모리 관리를 위한 비밀 팁에 대해 다뤄보겠습니다.

 

변수 선언 시 주의

자바스크립트에서는 변수를 선언할 때 var, let, const 키워드 중 하나를 사용합니다. 이 중 var는 함수 스코프를 갖고 있고, let과 const는 블록 스코프를 갖습니다. 블록 스코프 변수는 더 이상 필요하지 않을 때 자동으로 제거됩니다. 그러나 var 변수는 함수가 종료될 때까지 남아있을 수 있습니다.

 

 

JavaScript에서 var, let, const의 차이점

JavaScript에서 변수를 선언하는 키워드로는 var, let, const가 있습니다. ES6에서 새로 추가된 let과 const 키워드는 var 키워드와 다른 특징을 가지고 있습니다. 이번 글에서는 let과 const 키워드가 var 키워

ccusean.tistory.com

 

따라서 변수를 선언할 때는 가능한 한 let과 const를 사용하는 것이 좋습니다. 그렇지 않으면, 변수가 더 이상 필요하지 않을 때 수동으로 null로 설정하여 메모리에서 제거해야 합니다.

 

예시 코드

function example() {
  console.log(counter);
  for(var counter = 1; counter < 5; counter++) {
    console.log(counter);
  }
}

example(); // undefined, 1, 2, 3, 4

위 코드에서는 example 함수 내부에서 counter 변수를 선언하고, 이를 for 루프에서 사용합니다. 그러나, 변수가 선언되기 전에 console.log 함수에서 호출되므로, 변수가 정의되지 않았다는 undefined가 출력됩니다.

 

이러한 현상은 var 키워드를 사용할 경우, 해당 변수가 함수 스코프를 갖기 때문에 발생합니다. 따라서 변수를 선언할 때는 가능한 한 let이나 const 키워드를 사용하는 것이 좋습니다.

 

큰 객체를 작은 객체로 분할

JavaScript에서 객체는 참조형 데이터이기 때문에 메모리 사용이 큽니다. 따라서 큰 객체를 작은 객체로 분할하여 메모리 사용량을 줄이는 것이 좋습니다.

 

이를 위해 객체를 작은 조각으로 나누어 사용하는 것이 좋습니다. 예를 들어, 대규모 객체를 필드별로 작은 객체로 나누어 사용하면, 필요한 필드만 가져와서 사용할 수 있습니다. 이렇게 하면 메모리 사용이 줄어들고 성능도 향상됩니다.

 

예시 코드

const person = {
  name: 'John',
  age: 30,
  address: {
    street: '123 Main St',
    city: 'New York',
    state: 'NY'
  }
};

const personName = {
  firstName: person.name.split(' ')[0],
  lastName: person.name.split(' ')[1]
};

const personAddress = {
  street: person.address.street,
  city: person.address.city,
  state: person.address.state
};

console.log(personName); // { firstName: 'John', lastName: undefined }
console.log(personAddress); // { street: '123 Main St', city: 'New York', state: 'NY' }

위 코드에서는 대규모 객체 person을 작은 객체인 personName과 personAddress로 분할하여 사용합니다. personName 객체는 person 객체의 name 속성에서 firstName과 lastName 속성을 추출하여 사용하고, personAddress 객체는 person 객체의 address 속성에서 street, city, state 속성을 추출하여 사용합니다.

 

이를 통해 person 객체를 통째로 사용하는 것이 아니라, 필요한 속성만 사용하여 메모리 사용량을 줄일 수 있습니다.

 

중복된 데이터 제거

JavaScript에서 중복된 데이터를 사용하면 메모리 사용이 더욱 증가합니다. 따라서 중복된 데이터를 제거하여 메모리 사용량을 줄이는 것이 좋습니다.

 

이를 위해 중복 데이터를 찾아내고, 이를 함수로 분리하여 재사용하면 됩니다. 이를 통해 코드 중복도 감소시킬 수 있고, 메모리 사용도 줄일 수 있습니다.

 

예시 코드

function getName() {
  return 'John';
}

function getAddress() {
  return {
    street: '123 Main St',
    city: 'New York',
    state: 'NY'
  };
}

const person1 = {
  name: getName(),
  address: getAddress()
};

const person2 = {
  name: getName(),
  address: getAddress()
};

console.log(person1); // { name: 'John', address: { street: '123 Main St', city: 'New York', state: 'NY' } }
console.log(person2); // { name: 'John', address: { street: '123 Main St', city: 'New York', state: 'NY' } }

위 코드에서는 중복된 데이터인 'John'과 { street: '123 Main St', city: 'New York', state: 'NY' }를 함수로 분리하여 getName()과 getAddress() 함수로 정의합니다. 이를 통해 person1과 person2 객체에서 중복된 데이터를 사용하지 않고, getName()과 getAddress() 함수를 재사용하여 사용합니다.

 

이를 통해 중복된 데이터를 사용하지 않아 메모리 사용량을 줄일 수 있습니다.

 

적절한 클로저({}) 사용

클로저는 자바스크립트에서 매우 강력한 기능 중 하나입니다.

하지만 클로저 사용에 주의해야 할 점이 있습니다. 클로저는 자바스크립트에서 블록 스코프 변수를 사용할 수 있게 해주는 기능입니다. 그러나 클로저를 남용하면 메모리 누수가 발생할 수 있습니다.

 

예를 들어, 클로저 내부에서 사용하는 변수가 클로저 외부에서도 사용될 경우, 해당 변수는 클로저가 제거되어도 메모리에서 제거되지 않습니다. 이는 메모리 누수로 이어질 수 있습니다.

 

따라서 클로저를 사용할 때는 클로저 내부에서 사용하는 변수를 최소화하는 것이 좋습니다. 또한, 클로저를 사용하기 전에는 반드시 해당 변수가 메모리에 유지될 필요가 있는지 고려해야 합니다.

 

예시 코드

function add() {
  let count = 0;
  return function() {
    count++;
    console.log(`Count: ${count}`);
  }
}

const incrementCount = add();
incrementCount(); // Count: 1
incrementCount(); // Count: 2
incrementCount(); // Count: 3

위 코드에서 add 함수는 내부에서 count 변수를 선언하고, 해당 변수를 반환하는 함수를 반환합니다. 반환된 함수는 클로저를 형성하여 add 함수 내부의 변수 count를 참조합니다.

 

이를 통해 incrementCount 함수가 실행될 때 마다 count 변수가 증가되고, 호출 횟수가 기록됩니다. 이러한 방식으로 클로저를 사용하면, add 함수의 내부 변수를 외부에서 접근하지 않아도 호출 횟수와 같은 정보를 유지할 수 있습니다.

 

적극적인 가비지 수집

JavaScript는 가비지 수집기를 사용하여 메모리 관리를 수행합니다. 가비지 수집기는 더 이상 사용되지 않는 메모리를 자동으로 제거합니다.

 

그러나 가비지 수집기는 일반적으로 메모리 관리에 미약한 영향을 미치는 경우가 많습니다. 따라서 가능한 한 적극적으로 가비지 수집을 수행하는 것이 좋습니다.

 

가비지 수집을 수동으로 트리거하는 방법도 있습니다. 예를 들어, 객체를 더 이상 사용하지 않을 때, null로 설정하여 가비지 수집기가 해당 객체를 메모리에서 제거하도록 하는 것입니다.

 

예시 코드

function createObject() {
  const obj = {
    name: 'John',
    age: 30
  };
  // ... object manipulation ...
  return obj;
}

let myObject = createObject();
// ... use myObject ...

// No longer need myObject
myObject = null;

위 코드에서는 createObject 함수를 통해 객체를 생성한 후, myObject 변수에 할당합니다. 이후, 객체를 더 이상 사용하지 않게 되면, myObject 변수를 null로 설정하여 해당 객체를 가비지 수집하도록 합니다.

 

이를 통해 사용하지 않는 객체가 메모리에 머무르지 않고, 적극적으로 가비지 수집을 수행할 수 있습니다.

 

메모리 프로파일링 도구 사용

마지막으로, 메모리 누수를 찾는 가장 쉬운 방법은 메모리 프로파일링 도구를 사용하는 것입니다.


메모리 프로파일링 도구는 실행 중인 코드에서 메모리 사용량을 분석하는 도구입니다. 이를 통해 메모리 누수가 발생하는 지점을 찾아내고, 이를 수정하여 메모리 사용량을 줄일 수 있습니다.

 

Chrome 개발자 도구와 같은 메모리 프로파일링 도구는 자주 사용되는 도구 중 하나입니다. 이를 통해 JavaScript에서의 메모리 관리를 더욱 효율적으로 수행할 수 있습니다.

 

이상으로 JavaScript에서 효율적인 메모리 관리를 위한 비밀 팁에 대해 다뤄보았습니다. 이를 참고하여 코드를 작성하면, 성능 개선과 메모리 사용량 감소를 동시에 달성할 수 있습니다. 이러한 팁들은 JavaScript를 사용하는 모든 개발자에게 유용할 것입니다.

 

JavaScript에서의 메모리 관리는 개발자가 중요한 역할을 수행합니다. 메모리 누수가 발생하면 성능 저하와 서비스 장애로 이어질 수 있습니다.

 

따라서 개발자는 코드를 작성할 때, 메모리 관리에 대해 항상 염두에 두어야 합니다. 위에서 소개한 팁들을 활용하여 메모리 누수를 방지하고, JavaScript 코드의 성능을 개선하는 것이 좋습니다.

 

이상으로 "JavaScript에서 효율적인 메모리 관리를 위한 비밀 팁"에 대한 글을 마치겠습니다. 참고하시기 바랍니다.

반응형

댓글