본문 바로가기
개발(Development)/JS(자바스크립트)

[자바스크립트] 콜스택/메모리힙 구조, 데이터 저장/참조 원리

by 카레유 2021. 4. 7.

이 글은 자바스크립트의 콜스택/메모리힙에서 데이터가 어떤 방식으로 저장되고 참조되는지를 정리한다.

 

기본적인 메모리 구조와 변수 생성 원리에 대해서는 아래 글을 꼭 참고(필수)

[자바스크립트] 메모리 구조, 원시타입 변수 생성 원리, 가비지컬렉터


# 콜스택, 메모리힙이란?

자바스크립트는 콜스택과 메모리힙이라는 메모리 구조를 통해 데이터 및 코드 실행을 관리한다.

자바스크립트 콜스택과 메모리힙

 

1. 콜스택(Call Stack)

: 원시타입(숫자 등) 데이터가 저장된다.

: 실행컨텍스트(Execution Context)를 통해 1) 변수 식별자(이름) 저장, 2) 스코프 체인 및 this 관리, 3) 코드 실행 순서 관리 등을 수행.

* 실행 컨텍스트의 상세 구조 및 원리는 이 글의 범위를 넘어가므로 다루지 않습니다.

 

2. 메모리힙(Memory Heap)

: 참조타입(객체 등) 데이터가 저장된다.


# 콜스택, 메모리힙의 데이터 구조

원시타입은 콜스택에 저장되고, 참조타입은 메모리힙에 저장된다.

자바스크립트 메모리 구조: 콜스택, 메모리 힙

 

1. 원시타입 데이터(파란색 변수 a)

: 10이라는 값 자체는 원시타입이므로 콜스택에 저장된다.

: 변수 a에는 10이 저장된 콜스택 메모리의 주소값이 저장된다.

* 변수 식별자 a 자체는 콜스택 상의 '실행컨텍스트(Execution Context)의 렉시컬 환경(Lexical Environment)'이라는 곳에 저장된다.

 

2. 참조타입 데이터(핑크색 변수 b, c, d)

: 배열, 객체, 함수 등은 참조타입이므로 메모리 힙에 저장된다.

: 참조타입 데이터가 저장된 메모리힙의 주소값은 콜스택에 각각 저장된다.

: 메모리힙의 주소값이 저장된 콜스택의 주소값은 각각 변수 b, c, d에 저장된다.

* 마찬가지로, 변수 식별자 b, c, d 이름 자체는 콜스택 상의 '실행컨텍스트(Execution Context)의 렉시컬 환경(Lexical Environment)'에 저장된다.

 

이제 좀 더 상세하게 원시타입/참조타입 데이터가 콜스택과 메모리힙에서 어떻게 관리되는지 정리해보겠다.


# 원시타입의 변수 데이터

1. 원시타입 변수 생성

원시타입의 데이터 값은 콜스택에 저장되고,

데이터 값이 저장된 콜스택의 주소값은 변수 a, b 각각 저장된다.

(변수 a, b 식별자 자체는 실행컨텍스트의 렉시컬 환경에 저장된다.)

 

2. 원시타입 재할당 - Case1

변수 a 20 재할당하면

본인의 메모리에 있는 값을 변경하는게 아니라기존에 20 저장하고 있는 메모리의 주소값으로 교체한다.

a 저장된 주소값은 20 가리키고 있던 b 저장된 주소값과 동일해진다.

 

3. 원시타입 재할당 - Case2

변수 b  30 재할당하면,

변수 b 주소값이 가리키는 메모리에 저장된 20 30으로 교체하는게 아니라,

새로운 메모리를 확보하여 30 저장하고변수 b 저장된 주소값을 해당 주소값으로 교체한다.

 

4. 가비지 컬렉터

더이상 참조되지 않는 데이터는가비지 컬렉터에 의해 적절한 시점에 메모리에서 해제된다.


# 참조타입의 변수 데이터

1. 참조타입 변수 생성

배열과 같은 참조타입 데이터는 메모리 힙에 저장된다.

메모리 힙의 주소값은 스택에 저장되고a b에는 해당 콜스택의 주소값이 각각 저장된다.

(a는 const로, b는 let으로 선언된 것을 기억하자)

 

2. 참조타입 데이터의 값 변경

변수에 값을 재할당한게 아니라, 변수에 저장된 데이터를 수정한 것임에 주의하자.

 

메모리힙에 저장된 배열의 값을 변경하더라도배열이 저장된 메모리힙의 주소는 그대로다.

 

, 콜스택에 저장된 메모리힙의 주소는 변경되지 않는다.

따라서 변수 a b 저장된 주소값도 변하지 않는다.

a b입장에선 사실상 변한게 없는 것이다.

 

따라서 재할당이 필요 없는 경우, 참조타입은 const 선언하는게 좋다.

 

2. 참조타입 재할당

1) let으로 선언된 참조타입의 재할당

let으로 선언된 b 다른 배열을 할당하고 있다.

경우, 메모리 힙에 새로운 주소가 확보되고, 새로운 배열이 저장된다.

 

콜스택에 저장되는 메모리힙의 주소값도 새로운 주소로 변경이 필요하다.

이때 콜스택도 기존에 저장되어 있던 주소값을 바꾸는게 아니라, 새로운 메모리를 확보해서 새로운 메모리힙의 주소값을 저장한다.

 

따라서 변수 b 저장되는 콜스택의 주소값도 변경된다

 

* 참조타입은 동일한 구성의 객체를 생성하더라도, 매번 메모리를 확보하여 객체를 생성한다.

 

 

2) const로 선언된 참조타입의 재할당

const 선언된 a 다른 배열을 할당을 할당하면 에러가 난다.

 

메모리힙에 새로운 공간을 확보해 다른 배열을 저장하면,

콜스택에서도 새로운 메모리를 확보해 해당 메모리힙의 주소를 저장해야하는데,

이는 결과적으로 const 선언된 a 저장된 콜스택의 주소값도 변경하게 만든다.

 

const 선언된 변수는 본인에게 할당된 콜스택 주소값의 변경을 허용하지 않는다.

(이 것이 const의 정확한 의미가 아닐까 한다. 그래서 const로 선언된 변수는 반드시 초기값을 할당하면서 선언해야 한다)

 

따라서 코드는 실행이 불가능하다.

 

3. 동일한 구성의 참조타입 데이터

객체와 같은 참조타입 데이터는 동적으로 내부 요소가 변경될 있는 관계로,

동일한 요소의 객체를 생성하더라도 메모리힙에 각각 별도의 메모리 공간을 확보하여 저장된다.

 

따라서 me !== you 이다.


자바스크립트가 콜스택, 메모리힙을 이용해 어떤 식으로 데이터를 저장/참조 관리하는지를 정리해 보았다.

 

그런데 자바스크립트는 소스코드를 2단계로 나누어 실행한다.

 

1단계에서는 선언문들을 찾아서 변수 등을 실행 컨텍스트의 렉시컬환경에 등록한다.

2단계에서는 소스코드를 첫줄부터 차례로 실행하며 값을 할당하고 참조한다.

 

다음 글에서는 자바스크립트의 실행단계와 변수의 생성/할당/참조 과정을 정리해보기로 한다.

[자바스크립트] 코드 실행 2단계와 변수/함수 생성 과정

 

댓글