DeepDiveJS Chapter 11. 원시 값과 객체의 비교

[11장. 원시 값과 객체의 비교]

</br>

✏️ 자바스크립트의 값


  자바스크립트에서 사용되는 값의 타입을 여러 개로 나누었었다.

이것들을 메모리와 소통하는 방식에 따라서 분류해보면 원시 타입과 참조 타입(객체 타입)으로 나눌 수 있다.

  1. 원시 타입의 값을 변수에 할당하면, 변수에는 실체 값이 저장되며 변경이 불가능하다.
  2. 참조 타입의 값을 변수에 할당하면, 변수에는 내용이 저장된 메모리 공간의 주소가 저장되며 참조된 내용은 변경이 가능하다.

자바스크립트에서 변수에 저장된 원시 타입의 값들은 변경이 불가능하다. 사실 개발자가 원시 타입이 저장된 변수에 값을 수정하면, 같은 메모리 주소에 있는 값을 변경하는 것이 아니라 다른 주소에 새로운 값으로 재할당하게 되는 것이다.

반면에 객체 타입의 값은 변수에 주소를 저장하며, 주소가 가리키고 있는 값이 변경 가능하다.

</br>

✏️ 바구니를 통째로 버리기


  메모리를 바구니에, 변수를 바구니에 지은 이름으로 생각해서 본다면.

  1. 원시 타입

바구니에 담긴 내용물은 변하지 않으며, 내용물을 바꾸고 싶으면 기존의 바구니를 버리고 새로운 바구니를 준비해서 새로운 내용물을 담고 같은 이름표를 붙이는 것이다.

  1. 참조 타입

참조 타입의 바구니에는 얼마나 많은 내용물이 들어있을지 모른다. 통째로 버렸다가 새로 만드는데에는 비용이 너무 많이 들기 때문에, 내용물을 바꿀 수 있도록 하자.

대체 왜 이런 복잡하고 값마다 다르고 말도안되는 방식으로 값을 변경할까?

</br>

✏️ 원시 타입 값의 불변성


  메모리에 저장되어 있는 메모리를 재할당 하지 않고, 수정이 가능하도록 한다면 다른 메모리 활동 중에 충돌이 발생하거나 예기치 않게 수정될 수가 있기 때문이다.

컴퓨터는 커다란 알고리즘이고 시스템이기 때문에, 컴퓨터와 소통하는 프로그래밍 언어들 또한 오류를 최소화하려고 한다.

</br>

✏️ 참조 타입 값의 가변성과 문제점


  참조 타입의 값도 원시 타입의 값과 같은 문제를 공유하지만, 재생성에 너무 많이 비용이 들기 때문에 단점을 감수하고 변경이 가능하도록 선택되었다.

그렇기 때문에 변경이 불가능한 원시 값이 변경가능 했을 때 발생할 문제를 참조 값에서 유사하게 관찰해볼 수 있다.

</br>

✏️ 배열의 얕은 복사와 값의 공유


  자바스크립트에서 배열은 참조 타입의 값이다.

그렇기 때문에 자바스크립트에서 배열을 복사하면 배열의 내용이 아니라, 배열의 내용을 가리키는 주소를 복사해서 붙여넣게된다.

이렇게해서 발생하게 되는 문제가 얕은 복사에 의한 값의 공유이다.

1
2
var arr = [1, 2, 3];
var copiedArr = arr;

이와 같이 배열을 선언했다고 하자.

arr는 [1, 2, 3]이라는 배열을, copiedArr는 arr의 [1, 2, 3]이라는 내용을 복사한 것만 같지만.

사실 arr는 [1, 2, 3]이라는 배열을 가리키는 메모리 주소를 저장하고 있었으며, copiedArr에 복사하는 과정에서 이 메모리 주소를 복사한 것이 된다.

1
2
copiedArr[0] = 3;
console.log(arr); // [3, 2, 3];

그렇기 때문에, 복사된 배열의 값을 변경하면 기존 배열의 값 또한 변경되는 것이다.

이렇듯 주소로 배열을 복사하는 것을 얕은 복사라고 하며, 값이 공유되는 현상이 나타난다.

</br>

✏️ 모든 문제를 해결해주는 해결책은 없다.


  이런 단점이 있음에도 불구하고 값의 변경을 허용한 이유는 결국 효율성 때문이다. 객체의 특성상 메모리 주소가 어디까지 사용될지도, 얼마나 많은 내용을 담고 있는지도 모르기 때문에 원시 타입의 값과 같이 매번 재생성하고 재할당하는 것이 더 비효율적이다.

모든 문제를 해결해주는 해결책은 없다. 해결할 문제가 무엇인지, 각각의 문제 중 어떤 것에 집중하고 리스크를 안아야하는지 선택할 뿐인 것 같다.