자바 스크립트의 변수 타입에는 크게 Primitive type(원시타입)과 Reference Type(참조타입)으로 나누어져 있다. 원시타입(Primitive type)의 변수들은 데이터 복사가 일어날 때 메모리 공간을 새로 확보하여 독립적인 값을 저장하며 참조 타입은 메모리에 직접 접근이 아닌 메모리의 위치(주소)에 대한 간접적인 참조를 통해 메모리에 접근하는 데이터 타입이다.
자바스크립트에서 원시 타입 (string, number, bigint, boolean, undefined, ES6 부터 추가된 symbol) 은 변수에 할당될 때, 메모리의 고정 크기로 원시 값을 저장하고 해당 저장된 값을 변수가 직접적으로 가리키는 형태를 띈다. 또한 값이 절때 변하지않는 불변성을 갖고있기때문에 때문에 재할당 시 기존 값이 변하는것 처럼 보일지 몰라도 사실 새로운 메모리에 재할당한 값이 저장되고 변수가 가리키는 메모리가 달라졌을 뿐이다.
let a = 100;
a = 50;
a란 변수에 100이란 값을 할당하고 2번째 라인에서 50으로 재할당을 해준 예시이다. 첫 라인이 실행되면 메모리에 Number타입의 100이란 값이 생성되고 식별자 a는 메모리에 생성된 100의 메모리 주소를 가리킨다. 그후 두번째 라인이 실행되면 이전에 메모리에 생성된 100이란 값이 50으로 수정되는것이 아닌, 새로운 Number타입의 50이란 값을 새로운 메모리에 생성하고 a가 가리키던 메모리가 바뀌는것이다.
즉 메모리에는 100과 50이란 값이 모두 존재하고 있으며, 앞에서 말했듯이 원시타입은 불변성을 갖고 있기 때문에 기존에 메모리에 생성된 값들은 그 자체가 변경될 수 없다. 그저 식별자와 연결 되있는 메모리가 바뀌었기에 우리 눈에는 재할당 된 것처럼 보일뿐이다.
이를 고려하며 원시 타입의 값이 복사 될때는 어떤 일이 일어나는지 알아보자.
let a = 100;
let b = a;
a = 50;
console.log(b) // 100
새로운 변수 b에 a를 할당 하게되면 변수 b의 공간에는 a의 값을 값을 통째로 복사하여 변수의 메모리에 담게 된다. 그렇기에 변수 a가 50으로 재할당 되더라도 b는 전혀 영향을 받지 않는다.
자바스크립트에서 원시 타입을 제외한 나머지는 참조타입(객체(Object))이라 할 수 있다. 배열과 객체, 그리고 함수가 대표적이며, 원시타입과 가장 큰 차이점은 변수의 크기가 동적으로 변한다는 것이다. 이러한 특징 때문에 Object의 데이터 자체는 별도의 메모리 공간(heap)에 저장되며, 변수에 할당 시 데이터에 대한 주소 ( 힙(Heap) 메모리의 주소값)가 저장되기 때문에 자바스크립트 엔진이 변수가 가지고 있는 메모리 주소를 이용해서 변수의 값에 접근하게 되는것이다.
만일 let myArray = []라는 배열을 생성하면 위와 같은 일이 일어난다. 그림에서 볼 수 있듯이 원시타입의 값들은 값들이 직접적으로 저장되어 있지만, myArray (참조타입)는 Heap 메모리의 주소값이 저장되어 있다.
let myArr = [];
let copyArr = myArr;
myArr.push("hello");
console.log(copyArr); // ["hello"]
위 예제를 보면 알 수 있듯이, 참조 타입의 변수는 실제 데이터가 저장된 주소를 참조하기에 참조(reference) 타입이라고 불리는 것이다. 그렇기에 변수의 복사나 수정 시 참조 여부를 잘 고려해야 한다. 만일 이러한 특성을 고려하지 않은 채 중요한 정보를 담고있는 객체나 배열에 수정 및 복사를 가하게되면 원본 데이터가 예상치 못한 방향 으로 변경될 수 있으므로 항상 이를 고려하자.
좋은글 잘 읽었습니다