[JS] 메모리 모델(Memory Model)

jiseong·2021년 8월 12일
2

T I Learned

목록 보기
29/291
post-thumbnail

원시타입과 객체타입

자바스크립트의 모든 값은 7개의 데이터 타입을 가진다. 그리고 이들을 크게 원시타입객체 타입으로 구분할 수 있다.

  • 원시 타입 (primitive data type)
    • boolean
    • null
    • undefined
    • number
    • string
    • symbol (ES6에서 추가)
  • 객체 타입 (obejct / reference type)
    • object (원시 타입을 제외한 모든 것 function, array, etc.)

이 둘의 큰 차이점이라고 한다면 원시 타입은 변경 불가능한 값(immutable value)이고 객체 타입은 변경가능한 값(mutable value)이다.

그렇다면 변경 불가능한 값과 변경가능한 값이란 말은 무엇을 의미할까?
이 말을 이해하기 위해서 자바스크립트의 메모리 모델을 공부해봤다.

변경 불가능한 값이란?

다음과 같은 코드가 있다고 생각해보자.

let myNumber = 23;

해당 코드가 실행이 되면 자바스크립트는 아래와 같은 일을 수행한다.

    1. 변수의 고유 식별자(여기서는 myNumber)를 만든다.
    1. 런타임 시에 메모리에 주소를 할당한다.
    1. 할당된 주소에 23이라는 값을 저장한다.

위의 과정이 수행되고나면 다음과 같은 그림으로 표현될 수 있다.

그렇다면 할당된 변수를 새로운 변수(newVar)에 할당하면 어떻게 될까?

let newVar = myNumber;

newVar또한 23값을 가지고 있는 메모리주소를 가지며 이를 아래와 같이 나타낼 수 있다.

여기서 만약 기존의 myNumber변수에 +1을 해주면 어떻게 될까?

myNumber += 1;

물론 myNumber변수의 값이야 24로 되겠지만 newVar변수의 값은 어떻게 될지가 궁금하다. 결과를 먼저 보자면 아래와 같은 모습일 것이다.

자바스크립트는 myNumber += 1연산 수행결과로 24를 확인하게되면
메모리에 새로운 주소를 할당하고 이 할당된 주소에 24이라는 값을 저장 후 myNumber이 해당 주소를 가리키게 한다.
그렇기 때문에 newVar변수의 값은 그대로 23이게 된다.

이는 앞서 이야기한 원시 타입은 변경 불가능한 값이기 때문에 이러한 방식으로 동작하게 되는 것이다.


그렇다면 이러한 메모리 할당은 어디에서 일어날까? 에 대해서 알기 위해 자바스크립트의 메모리 모델을 알아보자.

자바스크립트의 메모리 모델

자바스크립트의 메모리 모델은 메모리 관점에서 크게 Call StackHeap으로 구분된다.

call stack 영역에서는 앞서 말한 원시 타입이 저장되며 heap 영역에는 객체타입(참조타입)이 저장된다. 앞서 설명한 myNumber변수와 newVar변수가 선언된 대략적인 표현을 그림으로 나타내면 아래와 같을 것이다.

여기서 heap 영역은 동적으로 변화할 수 있어 어느 정도의 메모리 공간을 확보해야 하는지 예측할 수 없는 배열, 객체 등과 같은 데이터들을 저장한다는 점이 포인트이다.

그렇다면 메모리 모델을 보았으니 변경가능한 값에 대해 알아보자.

변경가능한 값이란?

다음과 같은 코드가 있다고 생각해보자.

const myArray = [];

해당 코드가 실행이 되면 자바스크립트는 아래와 같은 일을 수행한다.

    1. 변수의 고유 식별자(여기서는 myArray)를 만든다.
    1. 런타임 시에 메모리에 주소를 할당한다.
    1. 런타임 시에 할당된 힙에 할당된 메모리 주소 값을 저장한다.
    1. 힙의 메모리 주소에 [ ]값을 저장한다.

원시 타입과 다르게 객체타입(참조타입)은 힙이라는 영역에 값을 저장하며 이를 그림으로 나타내면 아래와 같이 나타낼 수 있다.

그렇다면 할당된 변수의 값을 변경하려고 하면 원시 타입과 동일하게 주소가 바뀔까? 에 대한 의문이 들것이다.

myArray.push(1); // [1]
myArray.push(2); // [1, 2]
myArray.push(3); // [1, 2, 3]
myArray.push(4); // [1, 2, 3, 4]
myArray.push(5); // [1, 2, 3, 4, 5]

해당 코드가 수행되고 나면 최종적으로 myArray 변수에 [1, 2, 3, 4, 5]값이 저장이 될 것이다. 마찬가지로 결과부터 봐보자.

원시타입과는 다르게 myArray 변수의 메모리 주소는 변경되지 않는 것을 확인 할 수 있다.

이처럼 객체타입(참조타입)은 변경 가능한 값이기 때문에 이러한 방식으로 동작하게 되는 것이다.

한가지 궁금한점이있었다. myArray 변수를 선언할 때 const keyword를 사용했다. const를 배울 때 const는 변하지 않는 상수를 써줄 때 사용한다고 했는데 알고보니 “변하지 않는”이란 의미는 메모리 주소의 변경을 의미하는 것이였다. 그렇기 때문에 재할당할 목적이 아니면 오히려 const로 선언해주는 것이 좋다.


Reference

0개의 댓글