이 글은 '이웅모'님의 '모던 자바스크립트 Deep Dive' 책을 통해 공부한 내용을 정리한 글입니다. 저작권 보호를 위해 책의 내용은 요약되었습니다.
자바스크립트에선 7개의 원시타입이 존재한다.
원시타입은 다음과 같은 특성을 가지고 있다.
위 특성을 보면 마치 '원시타입의 값을 할당 받은 변수는 변경 불가능하다.' 라고 들린다. 하지만 변경 불가능하다는 것은 변수가 아니라 변수에 저장되어있는(가리키는) 값이다.
let num = 1;
num = 100;
위와 같이 변수 num을 100으로 재할당 했을 때의 상황을 그림으로 표현해보겠다. 메모리 주소지는 편의상 간략화 하였으며, 변수 선언문으로 인한 undefined는 생략하였다.
위 그림을 보면 변수 num이 할당 받은 최초의 공간(2번지)에서 값의 재할당이 이뤄지지 않고 새로운 공간(5번지)을 통해 값의 재할당이 이루어지는 것을 볼 수 있다. 기존의 원시 값 1은 변경되지 않았다. 따라서, 이 점에서 원시타입의 값은 변경 불가능한 값이라고 한다.
언뜻보면 비효율적인 과정으로 보이지만 원시 값이 변경 가능하다면 예기치 않게 변수 값이 변경될 수 있고 이는 상태 변경의 추적을 어렵게 만든다.
변수에 변수를 할당했을 때 말 그대로 값을 전달한다는 뜻이다.
let a = 1;
let b = a;
console.log(a); // 1
console.log(b) // 1
변수 b에 변수 a의 값을 할당하였다. 이때 a의 값은 1이므로 b 역시 1이란 원시 값을 갖는다. 하지만 a와 b의 1은 별개의 메모리 공간에 저장된 값이다. 그림으로 보면 다음과 같다.
따라서 변수 a의 값이 변경되어도 변수 b의 값에는 영향이 없다. 다만, 변수 a의 값이 변경되었을 때 메모리의 상황은 두 가지 경우의 수로 나온다. 이는 ECMAScript에서도 명확하게 정의되어 있지 않은 사항이다.
a = 2;
console.log(a); // 2
console.log(b); // 1
a = 2로 재할당이 되었다. 그러면 첫 번째 경우의 수는 다음과 같다.
애초에 변수 a와 b는 서로 다른 주소지의 원시 값을 가리키고 a = 2로 재할당을 받았으니 새로운 주소지인 6번지를 가리키게 된다. MDN에서도 이 방식으로 설명하고 있다. 다음은 두 번째 경우의 수다.
위 그림은 변수 b에 a를 할당할 땐 같은 주소지의 원시 값을 참조하다가 변수 a의 재할당이 일어날 때 서로 다른 메모리 공간을 가리킨다. 파이썬이 이와 같이 동작한다.
사실 자바스크립트에서 '값에 의한 전달'이란 표현은 애매하다. 변수와 같은 식별자는 값을 갖고 있는 것이 아닌 해당 값이 존재하는 메모리 주소를 가리키고 있기 때문이다. let a = 1;이라 하면 식별자 a는 원시 값 1이 존재하는 메모리 주소를 가리키는 주소값을 갖고 있다. 따라서 엄밀히 말하면 '값에 의한 전달'도 메모리 주소를 전달하는 것이다.
객체타입은 다음과 같은 특성을 가지고 있다.
객체는 변경 가능한(Mutable Value) 값이다. 따라서 객체를 할당받은 변수는 해당 메모리 공간에 참조 값(Reference Value)를 저장한다. 즉, 객체가 실제로 저장되어있는 메모리 공간의 주소를 가리킨다.
const a = {
name : "Kim"
};
위 코드를 그림으로 보면 다음과 같다.
객체는 크기가 원시 값처럼 일정하지 않고, 프로퍼티로 또다른 객체를 가질 수도 있어 메모리 사용의 효율성과 성능을 위하여 변경 가능하게 설계되었다. 따라서 원시 값과는 다르게 여러 개의 식별자가 하나의 객체를 참조할 수 있다는 것이다.
const a = {
name: "Kim"
};
// 얕은 복사
const b = a;
a.name = "Lim";
console.log(a); // { name: "Lim" }
console.log(b); // { name: "Lim" }
객체를 할당받은 변수는 객체의 실제 값이 아니라 객체가 있는 메모리 주소값을 갖는다고 하였다. 따라서 객체를 가리키는 변수를 타 변수에 할당하면 객체를 참조하는 참조값(주소값)이 복사되어 객체가 변경되면 변수 a와 b 모두 영향을 받는다. 즉, 식별자 a와 b는 하나의 객체를 공유한다고 볼 수 있다. 복사의 과정을 그림으로 보면 다음과 같다.
'값에 의한 전달'과 '참조에 의한 전달'은 결국 변수에 저장되어 있는 값이 원시 값이냐 참조 값이냐의 차이만 있을 뿐 식별자(변수)가 가리키는 메모리 공간에 저장되어 있는 값을 복사하여 전달한다는 면에서는 동일하다. 따라서 자바스크립트에는 '값에 의한 전달'만 존재한다고 말할 수 있으며 '공유에 의한 전달'이라고도 표현하기도 한다.