반응형

 

 

회사에서 타이머를 개선하던 중, setInterval 호출 주기에 따른 메모리 비용을 분석하면서,
JS Heap과 가비지 컬렉터에 대해서 공부하고 정리해보게 되었어요! 😎😎

 

 

JS Heap, 가비지 컬렉터
열심히 하자🔥

 


 

1. 메모리 관리란 무엇인가?


자바스크립트가 어떻게 메모리를 관리하는지 알아보려면, 먼저 메모리 관리가 무엇인지 이해해야 해요.
컴퓨터 프로그램은 데이터를 처리하기 위해 메모리라는 공간을 사용하고,
이 메모리에는 변수를 저장하거나 객체를 생성하는 등의 작업이 이루어집니다.
메모리를 효과적으로 관리하지 않으면, 프로그램의 성능이 떨어지거나, 메모리 누수가 발생할 수 있어요.

자바스크립트는 자동 메모리 관리를 제공합니다. 즉, 프로그래머가 직접 메모리를 할당하거나 해제하지 않아도, 자바스크립트 엔진이 이를 자동으로 처리합니다. 그 과정에서 JS Heap가비지 컬렉터가 중요한 역할을 하죠.

 



2. 자바스크립트의 메모리 구조

자바스크립트에서 메모리는 크게 두 가지 영역으로 나눌 수 있어요: 

1. 스택(Stack): 함수 호출, 원시 타입(숫자, 문자열, 불리언 등) 데이터를 저장하는 곳이에요. 빠른 속도를 자랑하며, 고정된 크기의 데이터를 처리할 때 사용됩니다.
2. 힙(Heap): 동적으로 생성된 객체나 배열, 함수 같은 복잡한 데이터 구조가 저장되는 곳입니다. 크기가 고정되지 않은 데이터를 저장하는데 적합하죠.

이 글에서 집중할 것은 바로 힙(Heap)이에요!

왜냐하면 자바스크립트에서 메모리 관리는 대부분 힙에서 이루어지며, 가비지 컬렉터도 이 영역을 관리하니까요.

 



3. JS Heap이란 무엇인가?

힙(Heap)은 메모리의 구조 중 하나로, 자바스크립트에서 객체, 함수, 배열 등이 저장되는 영역입니다. 이 메모리 영역은 크기가 고정되지 않고 동적으로 할당되며, 프로그램 실행 중에 객체가 계속 추가되거나 삭제될 수 있습니다.

자바스크립트에서는 변수에 복잡한 데이터를 할당하면, 그 데이터는 힙에 저장되고, 변수는 힙에 저장된 데이터의 참조(reference)만 가집니다.

let person = { name: 'John', age: 30 };



위 예시에서 person 객체는 힙에 저장되고, 변수 person은 그 객체를 참조하는 포인터 역할을 합니다.
힙은 비정렬된 메모리 공간이기 때문에 데이터를 찾거나 할당하는 데 시간이 걸리지만,
동적으로 크기를 늘릴 수 있는 유연성을 제공합니다.

 


 

4. 가비지 컬렉터란 무엇인가?

 

자바스크립트 엔진은 필요하지 않게 된 메모리를 자동으로 해제하는 가비지 컬렉터(Garbage Collector)를 사용합니다.
이는 프로그래머가 메모리 관리를 일일이 하지 않아도 된다는 장점이 있죠.
하지만, 가비지 컬렉터가 어떻게 작동하는지 이해하는 것은 성능 최적화에 중요한 요소입니다.

가비지 컬렉터의 목표는 필요 없어진 객체를 식별하고, 이를 메모리에서 해제하는 것입니다. "필요 없어진 객체"란 정확히 무엇일까요?
가비지 컬렉터는 어떤 기준으로 이 객체를 판단할까요?

 

 



5. 참조와 가비지 컬렉션: 마크 앤 스윕 알고리즘

자바스크립트에서 가비지 컬렉션은 주로 참조에 기반하여 동작합니다.
특정 객체가 더 이상 프로그램에서 참조되지 않는다면, 해당 객체는 "필요 없다"고 판단되고 메모리에서 제거됩니다.
이를 위한 대표적인 알고리즘이 마크 앤 스윕(Mark and Sweep) 알고리즘입니다.

1. 마크 단계(Mark): 자바스크립트 엔진은 도달 가능한 객체들을 찾아 표시합니다. 도달 가능하다는 것은 프로그램이 해당 객체를 참조하고 있다는 뜻입니다.
   
   - 전역 변수나 현재 실행 중인 함수에서 참조하는 모든 객체를 추적합니다.
   
2. 스윕 단계(Sweep): 도달할 수 없는 객체들은 필요 없다고 판단하고, 메모리에서 제거합니다.

function createObject() {
    let obj = { name: 'John' };
}
createObject();
// 여기서 obj는 더 이상 참조되지 않기 때문에 가비지 컬렉터가 이를 제거할 수 있음.



위 예시에서 createObject 함수가 끝나면, obj는 더 이상 참조되지 않기 때문에 가비지 컬렉터에 의해 제거될 수 있습니다.

 



6. 가비지 컬렉션과 메모리 누수

가비지 컬렉터는 매우 똑똑하지만, 때로는 모든 메모리를 정리하지 못할 수 있습니다. 이런 상황을 메모리 누수(memory leak)라고 부르며, 이는 프로그램이 점점 더 많은 메모리를 사용하게 만들어 성능 저하를 유발할 수 있습니다.

메모리 누수가 발생할 수 있는 일반적인 경우는 다음과 같습니다:

- 전역 변수 사용: 전역 변수를 남발하면, 그 변수가 언제 참조되는지 추적하기 어렵습니다.
- 클로저(Closure): 클로저는 함수 내부에서 참조된 외부 변수를 계속 유지할 수 있기 때문에, 의도치 않게 메모리를 차지할 수 있습니다.
- 이벤트 리스너 미제거: DOM 객체에 걸어둔 이벤트 리스너를 적절히 제거하지 않으면, 해당 객체가 계속 메모리에 남아 있을 수 있습니다.

 


 

7. 성능 최적화를 위한 메모리 관리 팁

 

가비지 컬렉터는 자동으로 동작하지만, 메모리 관리를 개선하기 위해 신경 쓸 몇 가지 팁이 있습니다.

1. 전역 변수 최소화: 전역 변수는 프로그램 종료 시까지 메모리를 차지하므로, 필요한 범위 내에서만 사용하세요.
2. 클로저 사용 주의: 클로저를 사용할 때는 불필요하게 메모리를 유지하지 않도록 변수를 잘 정리해야 합니다.
3. DOM 이벤트 핸들러 관리: DOM 객체에 연결한 이벤트 리스너는 객체가 더 이상 필요 없을 때 적절히 제거해야 합니다.



결론

자바스크립트에서 메모리 관리는 자동으로 이루어지지만, 
이를 이해하고 가비지 컬렉션의 동작 방식을 알면 더 나은 성능을 가진 애플리케이션을 만들 수 있습니다. 
특히 복잡한 애플리케이션에서는 메모리 누수가 발생하지 않도록 주의를 기울여야 합니다. 
JS Heap과 가비지 컬렉터에 대한 기본적인 이해를 바탕으로, 더 효율적인 메모리 관리와 성능 최적화에 도전해 보세요!


반응형