JavaScript의 엔진은 Memory Heap과 Call Stack으로 구성되어 있다. 가장 유명한 것이 구글의 V8 엔진이다. JavaScript는 단일 스레드 프로그래밍 언어인데, 이 의미는 Call Stack이 하나라는 의미이다. 즉, 멀티가 되지 않고, 하나씩 각각 처리한다는 의미이다.
콜 스택(Call Stack)
메모리 힙(Memory Heap)
JavaScript는 콜 스택과 메모리 힙이라는 메모리 구조를 통해 데이터 및 코드 실행을 관리한다.
1. 원시 타입 변수 생성
원시 타입의 데이터 값을 콜스택
에 저장되고 데이터 값이 저장된 콜스택
의 주소 값은 변수 a, b에 각각 저장된다.
2. 원시 타입 재할당(1)
변수 a에 20을 재할당하면, 본인의 메모리에 있는 값을 변경하는 게 아니라, 기존에 20을 저장하고 있는 메모리의 주소 값으로 교체한다. a에 저장된 주소 값은 20을 가리키고 있던 b에 저장된 주소 값과 동일해진다.
3. 원시 타입 재할당(2)
변수 b에 30을 재할당하면, 변수 b의 주소값이 가리키는 메모리에 저장된 20을 30으로 교체하는게 아니라, 새로운 메모리를 확보하여 30을 저장하고 변수 b에 저장된 주소 값을 해당 주소 값으로 교체한다.
4. 가비지 컬렉터
더 이상 참조되지 않는 데이터는 가비지 컬렉터
에 의해 적절한 시점에 메모리에서 해제된다.
1. 참조 타입 변수 생성
배열, 객체, 함수와 같은 참조 타입 데이터는 메모리 힙에 저장된다. 메모리 힙의 주소값은 콜 스택에 저장되고 a와 b에는 해당 콜스택의 주소값이 각각 저장된다.
2. 참조 타입 데이터의 값 변경
변수에 값을 재할당한게 아니라, 변수에 저장된 데이터를 수정한 것임에 주의하자. 메모리 힙에 저장된 배열의 값을 변경하더라도 배열이 저장된 메모리 힙의 주소는 그대로이다.
즉, 콜 스택에 저장된 메모리 힙의 주소는 변경되지 않는다. 따라서 변수 a와 b에 저장된 주소값도 변하지 않는다. a와 b의 입장에서는 사실장 변한게 없는 것이다.
3. 참조 타입 재할당
let으로 선언된 b에 다른 배열을 할당하고 있다. 이 경우, 메모리 힙에 새로운 주소가 확보되고, 새로운 배열이 저장된다.
콜 스택에 저장되는 메모리 힙의 주소값도 새로운 주소로 변경이 필요하다. 이 때, 콜 스택도 기존에 저장되어 있던 주소값을 바꾸는게 아니라 새로운 메모리를 확보해서 새로운 메모리 힙의 주소값을 저장하게 된다.
따라서 변수 b에 저장되는 콜 스택의 주소값도 변경된다.
const로 선언된 a에 다른 배열을 할당하면 에러가 난다.
메모리 힙에 새로운 공간을 확보해 다른 배열을 저장하면, 콜 스택에서도 새로운 메모리를 확보해 해당 메모리 힙의 주소를 저장해야하는데, 이는 결과적으로 const로 선언된 a에 저장된 콜 스택의 주소값도 변경하게 만든다.
const로 선언된 변수는 할당된 콜 스택 주소값의 변경을 허용하지 않는다. 따라서 이 코드는 실행이 불가능하다.
4. 동일한 구성의 참조타입 데이터
객체와 같은 참조타입 데이터는 동적으로 내부 요소가 변경될 수 있는 관계로 동일한 요소의 객체를 생성하더라도 메모리 힙에 각각 별도의 메모리 공간을 확보하여 저장된다.
콜 스택이 가지고 있는 주소 값이 서로 다르기 때문에 me와 you는 서로 다른 객체로 인식하게 된다.