JavaScript 메모리 구조
자바스크립트는 스택과 힙 두 가지 영역을 사용하여 객체가 생성될 때 자동으로 메모리를 할당하고, 더 이상 사용하지 않을 때 가비지 컬렉터를 통해 메모리를 해제합니다. (전역변수, Window 객체도 힙 영역에 저장됩니다.)
JavaScript 엔진 (인터프리터 VS 컴파일)
자바스크립트는 최초 인터프리터 방식으로 만들어졌으며, 실행되는 플랫폼(브라우저 등)에 따라 인터프리터와 컴파일 방식이 혼합되어 사용되고 있습니다.
자바스크립트 엔진은 자바스크립트를 실행해 주는 프로그램으로 대부분 웹브라우저 (크롬 - V8, Safari - Webkit 등)으로 인터프리터 방식과 컴파일 방식 등 엔진 별로 목적에 맞게 사용됩니다.
컴파일 방식과 인터프리터 방식의 차이는 컴파일 유무입니다.
function sum () {
let result = 0
for (let i = 1 ; i <= 10 ; i++){
result += i;
}
return result;
}
sum();
sum();
sum();
- 위의 코드에서 컴파일 방식은 첫 번째 sum() 메서드 호출에서 결과 값을 기억하고 있어서 추가 연산이 필요하지 않는다. 반대로 인터프리터는 매번 연산을 해야 한다.
* 인터프리터 방식 : 한 번에 한 문장씩 번역하여 사용 (해석이 빠르고, 하드웨어에 종속적이지 않으나 실행 시간은 느림 - Ruby, Python 등)
* 컴파일 방식 : 프로그램 전체를 스캔 및 컴파일하여 기계어로 번역 (실행 시간은 빠르나 해석이 느리고 하드웨어에 종속적 - C, C++ 등)
* Java의 경우 하이브리드 방식으로 javac를 사용하여 컴파일 후 .class를 인터프리터 방식으로 실행
* JavaScipt는 최초 인터프리터 언어로 만들어졌으며 V8 엔진 등은 컴파일 방식을 사용한다. 코드를 먼저 인터프리터가 읽으며 실행하고, 필요에 따라 컴파일하는 경우 JIT(Just-In-Time) 컴파일러라고 부르며 Chrome, Mozila, Firefox 등에서 사용됩니다.
JavaScript Data Type
자바스크립트에서 데이터 유형은 기본형인 Primitive Type과 참조형인 Reference Type 두 가지로 나뉩니다.
Primitive Type에는 Number, String, Boolean, null, undefined, Symbol 등의 타입이 있으며 할당이나 연산 시 실제 값을 가져올 수 있는 주소값과 실제 값을 스택 영역에 저장합니다. 스택 안에도 바로 값을 꺼내는 것이 아닌 값을 가리키는 주소값이 존재합니다.
Reference Type은 Object 속성인 Array, Function, Date, Map, Set 등의 타입이 있으며 할당이나 연산 시 값을 담고 있을 주솟값을 힙 영역에 저장합니다.
JavaScript Life Cycle
자바스크립트에서 메모리는 메모리 할당, 메모리 사용, 메모리 해제 3 가지 과정을 거칩니다. 객체가 생성될 때 데이터의 타입에 맞춰 기본형이면 스택, 참조형이면 힙 영역으로 메모리를 할당하고, 할당된 값을 읽거나 쓰는 사용을 한 후, 더 이상 사용하지 않을 때 가비지 컬렉터를 통해 메모리를 해제합니다.
가비지컬렉터는 변수나 함수가 필요한 지 여부를 알고리즘을 통해 판단합니다. 이때 사용되는 것이 레퍼런스 카운팅 가비지 컬렉션(reference-counting garbage collection)과 마크 앤 스윕 알고리즘(the mark and sweep algorithm)입니다.
레퍼런스 카운팅 알고리즘
레퍼런스 카운팅 알고리즘은 스택에서 힙에 연결된 선(참조를 사용하고 있는 개수)을 카운팅 해서 사용하지 않는 객체를 판별하는 알고리즘입니다.
let son = {
name: 'John',
};
let dad = {
name: 'Johnson',
};
son.dad = dad;
dad.son = son;
son = null;
dad = null;
- 레퍼런스 카운팅 알고리즘은 다음과 같이 두 객체가 서로 참조하고 있으면 가비지 컬렉터가 수집 대상임을 판단할 수 없다는 단점이 있습니다.
마크 앤 스윕 알고리즘
마크 앤 스윕 알고리즘은 순환 참조 문제를 개선하기 위한 알고리즘으로, 단순히 참조 수를 카운팅 하지 않고, 루트 객체에서 도달할 수 있는지 여부를 검사하고 수집 대상을 마크하는 알고리즘입니다. (웹 브라우저에선 Window 객체)
JavaScript 메모리 저장 방식
스택 영역은 JS 엔진이 컴파일 시 데이터의 크기를 알고 있는 정적 데이터를 저장하는 영역입니다. 스택은 후입선출인 LIFO 방식으로 관리되며 호출이 완료되면 소멸합니다. 함수, 지역변수, 매개변수 등이 스택에 저장됩니다. (메모리 높은 주소에서 낮은 주소 방향으로 할당) 스택은 속도는 빠르지만 LIFO 방식과 소멸된다는 단점이 있습니다.
힙 영역은 사용자에 의해 메모리 공간이 동적으로 할당되고 해제됩니다. 즉, 객체나 함수를 저장하는 공간으로 고정된 양의 메모리를 할당하지 않고, 필요한 만큼의 공간을 할당해 줍니다.(메모리 낮은 주소에서 높은 주소 방향으로 할당)
힙은 속도는 스택에 비해 느리고, 운영체제별로 다르기 때문에 구현하기 어렵지만, 메모리에 동적 할당이 가능한 장점이 있습니다.
REFERENCE
https://erwinousy.medium.com/javascript
https://www.geeksforgeeks.org/memory-management-in-javascript/
https://charming-kyu.tistory.com/19
https://hwan1402.tistory.com/110
https://www.devbabu.com/primitive-and-reference-data-types-in-javascript/