전성빈의 사리사욕

[JavaScript]메모리 모델 본문

백엔드 로드맵따라가기/Language

[JavaScript]메모리 모델

Been2 2020. 8. 14. 00:55
728x90

Js에서는 변수를 선언하고 값을 저장하고 메모리에서 할당 하는 과정과 내용등을 알아보도록 하겠습니다.

primitive 변수들의 선언과 할당

 

primitive variable이란 객체가 아닌 단순한 변수들을 뜻합니다. number, string 등이 포함되어 있습니다.

non-primitive란 객체들을 뜻하며 object, array 등이 있습니다.

 

var num = 10;

위와 같은 코드를 실행하면 js에서 일어나는 과정입니다.

  1. num에 해당하는 Unique identifier를 생성한다.
  2. Memory에 주소를 할당한다.(Runtime에서 할당)
  3. 해당 주소에 값을 저장한다.

만약 num의 값을 변경한다면 원래의 num에 다른 값을 저장하지 않는다.

js의 immutable한 특성 때문인데, primitive variable의 값은 절대 변하지 않는 것 입니다.

 

num identifier에 새로운 메모리 주소를 할당하고 그곳에 값을 다시 저장합니다. 즉, 원래 있던 메모리 주소와는 전혀 달라집니다.


JavaScript의 메모리 모델 stack과 heap

 

자바 스크립트에는 stack과 heap, queue가 전부 존재하지만 변수와 객체를 다루는 것은 stack과 heap이 합니다.

그 구조를 보도록 하겠습니다.

 

 

Stack

 

stack은 CallStack이라고 불리우며 function call을 포함하여 primitive variable들이 저장되는 공간입니다. 

변수 저장에는 사용되지 않는 메모리 공간인 Queue(Event Loop)에 해야할 작업(Message)가 존재하면 이곳 CallStack으로 가져와 처리합니다.

 

CallStack은 수행이 끝나면 사라지기 때문에 이곳에 존재하는 primitive변수들은 범위가 함수로 국한됩니다.

 

 

Heap

 

Heap은 Stack과 달리 non-primitive(array, object)한것들이 위치합니다.

 


Non-primitive Data type들의 선언과 할당

 

객체들은 primitive의 선언과 할당과는 다르게 동작합니다. 

var array = [];

1. array라는 이름의 Unique identifier를 생성한다.

2. Heap에 메모리 주소를 할당한다.

3. 할당된 메모리 주소를 array에 저장한다.

4. Heap의 메모리 주소에 값을 저장합니다.

 

Non-primitive data type들은 primitive data type들과는 다르게 많은 값의 집합이기 때문에 변할 수 있어야 합니다. 따라서 mutable합니다.

 


let vs const

 

let과 var은 범위의 차이가 있지만 const는 메모리 주소를 재할당 할 수 없다는 점이 큰 차이를 지닌다.

primitive data type에서는 immutable하기 때문에 값을 변화시킬 수 없다. 새로운 값을 저장하기 위해서는 새로운 메모리 주소를 할당 받아 identifier에 저장해야하는데 const로 선언하면 메모리 주소를 변경할 수 없기 때문에 값을 변화시킬 수 없는것이다.

 

Heap에 저장되는 Non-primitive Data type은 mutable하기 때문에 값을 변화시킬수 있는데 실제로 동작시켜보면 그렇지 않다.

const array = [];
array = [1,2,3];

위와 같은 코드를 실제로 돌려보면 const형이기 때문에 값을 변화 시킬 수 없다고 뜨는데 이는 값이 저장되는 과정을 통해 이유를 알 수 있다.

 

모든 변수는 선언되면 Call Stack에 메모리 주소와 값이 할당 되는데 Heap에 할당되는 data들도 똑같이 Call Stack을 통해 관리 된다. Heap에 할당된 주소가 Callstack의 특정 메모리주소의 값으로 저장되는 식이다. 따라서 위 코드를 실행시키면 callstack에 위치하는 array라는 identifier의 메모리 주소의 value를 변경하려는 것이기 때문에 동작하지 않는다.

 

하지만 array.push()와 같은 Call Stack에 저장된 value가 아닌 Heap의 value를 변경하는 작업은 메모리 주소를 변경하지 않으니 동작한다. 따라서 Non-primitive Data type은 const로 선언하더라도 값을 변경할 수 있게 된다.

 


Js engine - global Memory - hoisting

728x90