가비지 컬렉션의 대상인 메모리에 대해서 알아보자.
메모리는 다음과 같은 생존 주기를 지닌다.
자바스크립트는 변수를 선언할 때 자동으로 메모리를 할당한다.
원시 타입 값들은 스택 영역에, 참조 타입의 값은 힙 영역에 저장되며, 그 주소값은 스택 영역에 저장된다.
또한 변수 식별자는 스택 영역 상의 실행 컨텍스트의 렉시컬 환경에 저장된다.
const a = 10; // 원시 타입은 메모리 스택 영역에 저장
const b = [1, 2, 3]; // 배열, 함수, 객체는 힙 영역에 저장
v8 엔진에 의해 전역 실행 컨텍스트 렉시컬 환영에 있는 식별자 a, b를 참조한다.
console.log(a); // 10
console.log(b[0]); // 1
쓸모없는 메모리 영역을 자동으로 해제해주는 것이 바로 가비지 컬렉터(GC)이다.
그렇다면 GC는 어떤 기준으로 메모리 영역을 더 이상 쓸모없다고 판단할까?
어떤 원리로 가비지 컬렉션이 동작할까?
프로그램을 실행하면 메모리의 빈 공간이 할당되는데, 이 할당된 공간을 'Resident Set'이라고 한다.
Resident Set은 크게 스택 메모리와 힙 메모리로 나뉜다.
(자바스크립트는 싱글스레드여서 스택 메모리를 하나만 가진다.)
스택은 함수 호출이 끝난 후 자바스크립트 엔진에 의해 정리되지만, 힙 메모리는 그렇지 않다. 따라서 힙에 있는 쓸모없는 메모리가 해제되지 않는다면, 메모리 누수 가 발생하여 프로그램 속도는 점점 느려질 것이다.
가비지 컬렉션이 일어나는 영역은 힙 메모리의
New space
와Old space
이다.
New Space | Old Space |
---|---|
- 새로 만들어진 모든 객체를 저장. - 짧은 생명주기. - 2개의 semi-space로 이루어짐. - minor GC가 관리함. | - Minor GC가 두 번 발생한 뒤 "New 영역"에서 살아남은 객체들이 이동하는 영역. - Major GC가 관리. - Old pointer space와 Old data space로 나뉘어짐. |
'실행 컨텍스트(Execution Context)'는 JavaScript 코드가 실행될 때 생성되는 환경을 나타낸다. 각 함수 호출, 블록 스코프, 전역 스코프 등 JavaScript 코드의 실행 맥락은 실행 컨텍스트로 표현된다. 실행 컨텍스트는 코드 실행에 필요한 여러 정보와 변수를 담고 있으며, 변수 식별자와 그 값들이 저장되는 환경을 가리킨다.
'렉시컬 환경(Lexical Environment)'은 실행 컨텍스트 내부의 일부로서, 변수와 함수의 식별자와 해당 변수 또는 함수의 값(또는 참조)을 관리하는데 사용된다.
이 렉시컬 환경은 스코프 체인과 함께 클로저, 스코프 규칙, 변수 및 함수의 스코프 등을 정의하는 데 중요한 역할을 한다.
따라서 문장 "변수 식별자 a 자체는 콜스택 상의 '실행 컨텍스트의 렉시컬 환경'이라는 곳에 저장된다"는 변수 'a'가 속한 스코프(실행 컨텍스트) 내의 렉시컬 환경에 저장된다는 의미다.
이 렉시컬 환경은 변수 'a'와 해당 값 또는 참조를 관리하며, 변수 'a'의 스코프에 대한 정보도 여기에 저장된다. 이러한 내부 환경은 변수와 함수의 스코프 결정 및 변수 식별자 해석에 사용된다.
스택(Stack) 메모리
스택 메모리는 함수 호출(call)과 관련된 데이터를 저장하는 데 사용된다. 함수가 호출될 때, 해당 함수의 로컬 변수, 매개변수 및 함수 내에서 사용되는 임시 데이터가 스택 메모리에 저장된다.
스택은 후입선출(Last-In, First-Out, LIFO) 구조를 가지며, 가장 나중에 호출된 함수가 가장 먼저 실행을 완료하고 메모리에서 제거된다.
따라서 스택은 함수의 호출과 반환을 관리하며, 함수가 끝나면 해당 함수와 연관된 데이터가 스택에서 제거된다.
이 과정은 자바스크립트 엔진 내에서 자동으로 이루어진다. 즉, 개발자가 직접 메모리를 해제할 필요가 없다.
힙(Heap) 메모리
힙 메모리는 동적으로 할당된 데이터와 객체를 저장하는 데 사용된다. 이러한 데이터는 함수 호출과는 관계없이 생성 및 소멸할 수 있다.
힙 메모리는 스택과는 다르게 개발자가 직접 메모리 할당 및 해제를 관리해야 한다.
메모리 할당은 개발자가 new
키워드나 다른 메모리 할당 메서드를 사용하여 이루어진다.
메모리 해제는 개발자가 필요 없는 데이터를 더 이상 참조하지 않을 때, 해당 데이터에 대한 참조를 제거하거나 더 이상 필요하지 않은 객체에 대한 참조를 제거함으로써 이루어진다.
일반적으로 가비지 컬렉션(Garbage Collection)
이라는 메커니즘을 사용하여 더 이상 필요하지 않은 데이터를 정리하고 메모리 누수를 방지한다.
결론
스택 메모리의 경우 자바스크립트 엔진이 함수 호출과 관련된 데이터를 자동으로 정리하고 메모리 관리를 처리하며, 힙 메모리의 경우 개발자가 메모리 할당과 해제를 직접 관리해야 한다는 차이점이 있다.
참고