게으른개발너D
Javascript Memory 본문
변수를 선언할 때 자바스크립트 내부에선 어떤 일이 발생할까?
해당 코드를 실행할 때 자바스크립트는 변수에 고유식별자를 생성하고 메모리에 주소를 할당한다.
최종적으로 생성한 주소에 값을 넣게 된다.
이 과정을 시각화 하면 다음과 같다.
우리가 선언한 변수나 상수는 값을 바라보고 있는 것이 아닌 메모리 주소를 바라보고 있다.
만약 여기에 새로운 변수에 기존 변수를 대입하면 어떻게 될까?
답은 간단하다.
아래 그림과 같이 기본 변수의 메모리 주소를 참조하게 된다.
만약 기존 변수를 조작하면 어떻게 될까?
두번째 생성한 변수의 값도 변하게 될까?
이번에는 그렇지 않다.
새로운 메모리 주소를 할당 받고 그곳에 값을 넣게 된다.
그 이유는 자바스크립트에서 원시 값은 변경이 불가능하기 때문이다.
따라서 원시 타입의 값이 변경될 때엔 항상 메모리가 새로 할당된다.
변수 선언에 따른 Virtual Machine
자바스크립트 엔진은 가상 머신으로 구성이 되어있다.
이 가상 머신의 메모리 모델은 아래와 같이 각각 Heap 영역과 Call Stack 영역으로 구성되어 있다.
Heap은 참조 타입이 들어가고 Call Stack엔 원시 타입이 들어가게 된다.
위에서 우리가 했던 과정을 Call Stack으로 표현하면 Stack처럼 하나씩 쌓이게 된다.
만약 아래의 코드를 실행시키면 어떻게 될까?
let a = 10;
const b = 20;
const arr = [];
arr.push(5);
arr.push(3);
arr.push(1);
먼저 순차적으로 Call Stack에 변수들이 쌓이게 된다.
배열같은 경우 object 타입이기 때문에 참조 타입으로 분류된다.
배열을 생성하면 Heap에 배열 영역이 생성되는데 Call Stack에 생성된 배열 변수는 Heap에서 생성된 배열의 메모리 주소를 참조하게 된다.
여기서 Heap 영역 메모리는 동적으로 크기가 변할 수가 있다.
따라서 배열에 값을 추가하면 Heap 메모리 영역에 그대로 할당이 된다.
배열을 상수로 선언했는데 동작하는 이유기도 하다.
상수여도 push가 동작하는 이유는 Call Stack에 할당된 메모리를 변경하는 것이 아닌, Heap 메모리를 변경하는 것이기 때문이다.
여기서 모든 로직을 마쳤다.
그런데 사용을 마친 메모리는 어떻게 정리가 될까?
Garbage Collector
자바스크립트 엔진은 Garbage Collector라는 것을 통해 메모리를 정리한다.
Garbage Collector는 사용하지 않는 메모리를 해제하는 역할을 맡고있다.
앞서 사용된 메모리 주소도 Garbage Collector에 의해 정리될 수 있다.
이때 현대적인 브라우저의 가비지 콜렉터는 Mark and Sweep Algorithm을 통해 메모리를 정리하고 있다.
Mark and Sweep Algorithm
브라우저에서 최상위 객체인 window부터 시작하여 닿을 수 없는 주소를 더 이상 필요없는 주소로 정의하고 지우는 알고리즘
가장 왼쪽의 string은 닿지 않는다.
이런 경우엔 메모리에서 삭제된다.
다시 위의 상황으로 돌아가자.
만약 또 다시 값을 할당하여 첫 번째 메모리 값을 아무도 참조하지 않는다면 어떻게 될까?
가비지 콜렉터에 의해 조용히 사라지게 된다.
이처럼 메모리가 지워지는 것은 참조가 중요하다.
'개발 > JavaScript' 카테고리의 다른 글
흐름제어 (Control Flow, Data Flow) (0) | 2023.08.04 |
---|---|
표현식과 연산자 (Expressions and Operators) (0) | 2023.08.03 |
[Array] 까먹는 것 정리 (0) | 2023.07.12 |
[String] 까먹는 것 정리 (0) | 2023.07.12 |
[Object] 까먹는 것 정리 (0) | 2023.07.12 |