1. 정의
자바스크립트 엔진이 자바스크립트를 실행할 때 원시 타입 및 참조 타입을 저장하는 메모리 구조로 콜 스택과 힙을 갖는다.
1-1 콜스택
원시타입 값과 함수 호출의 실행 컨텍스트(Execution Context)를 저장하는 곳이다.
1-2 힙(메모리 힙)
객체, 배열, 함수와 같이 크기가 동적으로 변할 수 있는 참조타입 값을 저장하는 곳이다.
2. 동작 원리
let a = 10;
let b = 35;
let arr = [];
function func() {
const c = a + b;
const obj = { d: c };
return obj;
}
let o = func();
위 코드를 콜 스택과 힙의 동작으로 확인해 보자.
제일 처음으로 GEC(Global Execution Context, 글로벌 실행 컨텍스트)가 생성되고
원시 값은 콜스택에, 참조 값은 힙에 저장된다.
GEC가 생성된 뒤 함수가 실행하게 되고 FEC(Function Execution Context, 함수 실행 컨텍스트)가 생성되며 동일하게 원시 값은 콜 스택에, 참조값은 힙에 저장된다.
함수가 객체obj를 리턴하면 힙에 해당 값을 저장 후 FEC에 힙 메모리 주소를 저장한다.
그 후 o에 함수에서 반환된 객체 값을 할당하면 아래와 같다.
FEC는 함수가 값을 리턴했기 때문에 콜 스택에서 제거된다.
이제 콜 스택에 있는 o의 값은 객체 값이 저장된 힙 메모리 주소로 갖게된다.
전체 코드 실행이 끝나면 GEC가 콜 스택에서 제거된다.
GEC가 제거되면, 힙의 객체를 참조하는 스택의 값이 없기 때문에
가비지 컬렉션(Garbage Collector, GC)에 의해 제거된다.
3. 변수 데이터 할당과 재할당
3-1 원시 값
원시 값은 string, number, boolean, undefined, null, symbol이 있다.
할당
이 값들은 위에서 설명했듯이 콜 스택에 직접적으로 저장되며, 코드에서 변수 참조를 할 경우 콜 스택에서 바로 해당 값을 가져올 수 있다.
재할당
재할당의 경우 본인의 메모리에 있는 값을 변경하는 것이 아니라, 기존에 값을 저장하고 있는 메모리의 주소 값으로 교체한다.
a에 저장된 주소값은 20을 가리키고 있던 b에서 저장된 주소값과 같아지며, 새로운 값을 재할당한 b는 콜 스택에 새로운 메모리를 확보해 30을 저장하고 변수 b에 주소값을 새로운 주소값으로 교체한다.
가비지 컬렉션
이후 더이상 참조되지 않는 데이터는 가비지 컬렉션에 의해 적절한 시점에 메모리에서 해제된다.
3-2 참조 값
할당
참조 값은 메모리 힙에 저장되며, 메모리 힙 주소값은 콜 스택에 저장되고, a와 b에는 해당 콜 스택의 주소값이 저장된다.
값 변경
변수에 값을 재할당한 것이 아니라, 변수에 저장된 데이터를 수정한 것이다.
값 변경의 경우는 위의 사진에서 데이터를 수정한 것이기 때문에 힙의 주소는 같다.
즉, 콜 스택에 저장된 힙의 주소는 변하지 않는다.
재할당
변수가 let키워드를 이용해 선언되어 있어야지 재할당이 가능하고,
const 키워드로 선언되어 있으면 타입 에러가 발생한다.
재할당의 경우에는 새로운 힙 주소가 생기며 새로운 데이터가 저장된다.
콜 스택에 저장된 힙 주소 또한 바꿔야 하므로 새로운 메모리를 확보해 새로운 콜 스택 주소도 생기게 된다.
참조 값은 동일한 구성의 객체를 생성해도 매번 새 메모리를 확보해 새 데이터를 생성한다.
동일한 구성의 참조 값 데이터
객체와 같은 참조 값은 동적으로 내부 요소가 변경될 수 있으므로,
동일한 요소의 객체를 생성해도 메모리힙에 별도의 메모리 공간을 확보해 저장하게 된다.
즉, a !== b인 셈이다.
이 다음 글에서는 콜 스택과 힙에서 발생할 수 있는 메모리 누수와 이를 관리하는 가비지 컬렉션에 대해 정리할 예정이다.
'JavaScript > Javascript' 카테고리의 다른 글
자바스크립트 비동기와 이벤트 루프 (1) | 2023.10.07 |
---|---|
Javascript의 메모리누수와 가비지 컬렉션 (0) | 2023.10.06 |
IIFE (Immediately Invoked Function Expression, 즉시 실행 함수 표현식) (0) | 2023.10.04 |
변수, var 그리고 블럭 스코프를 갖는 let, const (0) | 2023.10.02 |
네이티브 객체와 호스트 객체 (0) | 2023.09.26 |