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

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

by 카레유 2021. 4. 7.

자바스크립트가 기본 타입 데이터를 저장, 참조하는 과정을 메모리의 관점에서 아주 단순화하여 정리해 본다.


# 메모리 구조, 데이터 저장/참조 원리

컴퓨터의 메모리는 1Byte(8bit)크기의 메모리셀 여러개 구성된다.

 메모리셀은 본인만의 고유한 주소값 가지며, 8개의 비트(2진수: 0, 1)로 데이터를 저장한다.

 

메모리 구조

1. 메모리 구성

: 컴퓨터 메모리는 1byte(8bit) 크기의 메모리셀 여러개로 구성된다.

 

2. 메모리 셀

: 각 메모리셀은 고유한 주소값을 갖으며, 메모리셀(1byte) 단위로 데이터를 저장하고 읽는다.

 

3. CPU와 메모리 역할

: CPU는 메모리에 저장된 값을 꺼내와 연산을 하고, 연산 결과를 다시 메모리에 저장한다.

 

4. 데이터 저장 방식

: 용량이 큰 데이터는 메모리셀(1byte) 여러개를 사용해 저장한다.

 

5. 데이터 읽기 방식

: 첫번째 메모리셀의 주소와 메모리셀의 갯수를 파악해 읽어들인다.

 

(참고) bit와 byte

* 1bit는 2진수(0, 1)값 한개가 저장되는 단위이다. 2개의 값을 저장할 수 있다.

* 1byte는 8bit이다. 2의 8승 까지 저장된다.


# 원시타입 변수 선언

아래와 같이 변수를 선언하면 메모리에선 어떤 일이 발생할까?

 

 let a = 10; 

 

자바스크립트는 내부적으로 let a;와 a= 10;으로 나누어 변수의 선언과 값의 할당을 수행한다.

a변수에는 10이 저장된 메모리의 주소값이 할당된다.

 

number 타입(64비트 부동 소수점 형식)의 데이터는 8바이트, 즉 메모리셀 8개를 사용해 저장된다.

변수 a에는 첫번째 메모리의 주소가 저장된다.

 

이 과정을 자세히 살펴보면 다음과 같다.

1. 변수 선언

: 자바스크립트는 소스 코드를 실행하기 전, 선언문(변수, 함수, 객체 등)을 먼저 스캔한다.

: let a 선언문을 발견하고, a변수를 '실행 컨텍스트'라는 곳에 등록한다.

 

2. 초기화

: 스캔작업이 완료된 뒤, 소스코드를 위에서부터 한줄씩 실행하기 시작한다.

: let a; 구문을 만나면, 메모리에 공간을 확보하고 undefined를 할당하여 초기화 한다.

: 변수 a에는 해당 메모리의 주소값을 저장한다.

 

3. 데이터 타입 체크

: a=10; 구분을 만나면,

: 10이라는 값이 number타입의 64비트 부동소수점 형식임을 파악한다.

 

4.새로운 메모리 확보 및 값 할당

: number타입 크기인 8바이트(64비트)의 메모리 공간을 새로 확보하고,

: 10을 저장한다.(실제로는 이진수 1010 8비트씩 8개 바이트로 저장)

* 기존에 할당된 메모리에 저장된 undefined를 10으로 변경하지 않음에 주의!

 

5. 주소값 저장

: a 변수에 10이 저장된 새로운 메모리의 첫번째 셀 주소값을 저장


# 원시타입 변수 참조

아래 코드처럼 변수 a를 참조하면 어떤 일이 벌어질까?

 

 console.log(a); 

 

변수에 저장된 것은 메모리 주소값이지만,

변수를 참조하면 주소값이 아니라, 주소값이 가르키는 메모리에 할당된 2진수(bit)를 해석한 값이 반환된다.

 

1. 주소값 확인

: a 변수에 저장된 주소값 확인(첫번째 메모리셀의 주소)

 

2. 데이터 타입 체크 => 메모리 크기 파악

: number 타입이므로 8byte의 메모리 셀이 사용되었음을 파악

 

3. 데이터 읽기

: 첫번째 주소값에서부터 8byte만큼의 데이터를 읽는다.

 

4. 값의 해석 및 반환

: 메모리에서 읽어 들인 2진수 값을 number 타입의 숫자 10으로 해석하여 반환한다.

* string 타입이라면 문자열로 해석하여 반환한다.


# 값의 재할당

그렇다면, 이미 값이 할당된 변수 a에 다른 값을 할당하면 어떻게 될까?

 

 a = 20; 

 

값을 재할당하면 기존 메모리에 저장된 값을 변경하는게 아니라,

새로운 메모리를 확보하여 값을 저장하고, a변수에 저장된 메모리 주소값을 변경한다.

 

1. 데이터 타입 체크

: 20은 number타입의 64비트 부동소수점 형식임을 파악

 

2. 새로운 메모리 공간 확보

: 8바이트(64비트) 메모리 공간을 새로 확보(메모리셀 8개)

 

3. 새로운 값 할당

: 8바이트의 메모리셀에 20을 할당(2진수로!)

 

4. 변수 a의 주소값 변경

: a 변수에 새로운 메모리의 주소값을 저장

 

5. 기존 값 제거

: 더 이상 참조되지 않는 기존 값은 '가비지컬렉터'에 의해 메모리에서 해제

 

 

즉, 기존 메모리에 저장된 값을 변경하는게 아니라,

새로운 메모리를 확보해 새로운 값을 저장하고, 변수에 해당 메모리 주소값을 저장하는 것이다.

(이는 자바스크립트의 원시값이 변경 불가능한 값이기 때문이다.)

 

그런데 만약 이미 20이 저장된 메모리 공간이 있다면?

새로 메모리 공간을 확보하지 않고, 20이 저장되어 있던 기존의 메모리 주소값을 할당하게 된다.

 

 let a = 10; 

 let b = 20; 

 a = 20; 

 

즉, 위의 코드를 실행하면 a와 b에 저장된 메모리 주소값이 동일해진다.

a와 b에 둘다 20이 저장된 메모리 주소값이 할당되는 것이다.

 

변수 a 20 재할당하면

본인의 메모리에 있는 값을 변경하는게 아니라,

기존에 20 저장하고 있는 메모리의 주소값으로 교체한다.

 

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

 

변수 b  30 재할당하면 

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

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

 

더 이상 그 무엇에도 참조되지 않는 10은 적절한 시점에 가비지 컬렉터에 의해 메모리에서 제거된다.


# 가비지 컬렉터

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

단, 정확히 언제 메모리에서 해제될지는 알 수 없다.(자바스크립트 마음대로다.)

 

위의 예제에서는 10이 가비지 컬렉터의 먹잇감이 될 가능성이 높다.


지금까지 자바스크립트의 '원시타입' 변수의 생성과정을 메모리의 관점에서 아주 단순화해서 정리해보았다.

 

그런데 사실 자바스크립트는 '콜스택'과 '메모리힙'이라는 구조를 통해 코드의 실행과 데이터 관리를 수행한다.

 

콜스택은 '원시타입' 데이터를 저장하고 '실행 컨텍스트'를 관리하며,

메모리힙은 '참조타입'(객체 등) 데이터를 저장한다.

 

이에 대해서는 다음 글에서 정리하기로 한다.

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

 

 

댓글