자바스크립트 세부 데이터 타입(Array, String ...)의 성질을 살펴보기 보다 기본형과 참조형의 특징이 무엇이고 어떻게 구분하는지 다룹니다.
자바스크립트 데이터 타입 이해하기
자바스크립트 데이터 타입은 크게 두 종류입니다. 기본형(원시형, primitive type)과 참조형(reference type)이다. 이에 따른 세부 데이터 타입은 다음과 같습니다.
기본(원시)형 → Number
, String
, Boolean
, null
, undefined
, Symbol
참조형 → Object
, Array
, Function
, Date
, RegExp
, Map
, WeakMap
, Set
, WeakSet
, 참조형은 모두 객체(Object
)의 하위 분류에 속합니다.
기본형과 참조형을 구분하는 기준
기본형은 값이 담긴 주솟값을 바로 복제하는 반면, 참조형은 값이 담긴 주솟값들로 이뤄진 묶음을 가리키는 주솟값을 복제합니다. - <코어자바스크립트> 2p
이 인용문을 이해하려면 약간의 배경지식이 필요합니다.
주솟값은 '컴퓨터 메모리의 주소 값'을 의미합니다. 컴퓨터 메모리(이하 메모리)에는 데이터가 저장되고 메모리의 주소는 그곳에 저장된 데이터를 가리킵니다. 메모리에는 식별자(변수명), 문자열, 객체, 배열 등 모두 담길 수 있습니다.
자바스크립트에서 변수 선언식을 적어보겠습니다.
var a;
컴퓨터가 이 한 줄의 명령을 실행하면, 메모리의 변수 영역에 (내부적으로 정해진 규칙에 따라) 특정 주소의 메모리 공간에 데이터를 할당합니다. 예를 들어, 이 데이터의 (임의로 정한) 주소는 1234
이며, 이 데이터의 식별자는 a
이며, 이 데이터의 값은 없습니다.
이제 컴퓨터는 a
를 메모리의 1234번지에 있는 값
으로 인식할 것입니다. 하지만 지금은 값이 없으니 값을 할당해보겠습니다.
a = 'hello'
컴퓨터가 이 명령을 실행하면, 메모리 1234
번지에 존재하는, a
라는 이름을 가진 데이터의 값은 'hello'
가 됩니다. 하지만 실제로 1234번지의 메모리에 'hello'
가 저장되지 않습니다. 'hello'
는 메모리의 (내부 규칙에 따라) 별도의 데이터 영역에 저장됩니다. a
의 값으로 저장되는 것은 이 'hello'
가 저장된 메모리의 주소입니다.
예를 들어, 'hello'
가 저장된 메모리의 주소가 5678
번지라면, 1234
번지의 데이터 a
의 값은 5678
이 됩니다. 즉, a
는 실제 데이터('hello'
)를 가지고 있는 게 아니라, 데이터의 참조값(주소, 5678
)를 가지고 있는 것입니다.
다시 위의 인용문을 가져와 보겠습니다.
기본형은 값이 담긴 주솟값을 바로 복제하는 반면, 참조형은 값이 담긴 주솟값들로 이뤄진 묶음을 가리키는 주솟값을 복제합니다.
기본형 데이터는 값을 할당할 때마다 매번 새로 데이터를 만들어 메모리의 데이터 영역에 할당하고 그 주솟값을 식별자의 값에 복제합니다. 예를 들어, var a = 'hello' + 'There'
의 경우, 컴퓨터는 이 명령을 실행하고 5678
번지의 데이터, 'hello'
를 'helloThere'
로 교체하지 않습니다. 새로 5679
번지에 공간을 할당해 'helloThere'
값을 넣습니다. 그리고 a
의 값을 5678
에서 5679
로 바꿉니다.
따라서 위에서 선언하고 데이터를 할당한 a
의 값인 'hello'
이나 이후의 값인 'helloThere'
의 데이터 타입은 기본형입니다. 메모리의 데이터 영역에 선언된 기본형 데이터는 바뀌지 않습니다, 불변값입니다.
그에 반해 참조형 데이터는 바뀔 수 있습니다, 즉 가변값입니다. 아래와 같은 참조형 데이터를 할당할 때 컴퓨터가 어떻게 명령을 실행하는지 예시를 들어보겠습니다.
var apple = {
color: "red",
price: 1000
};
- 컴퓨터는 변수 영역의 빈 공간(주소
1235
번지)을 확보하고, 그 주소의 이름(식별자)을apple
로 정합니다.1235
번지(식별자:apple
)의 값을 저장하기 위해 데이터 영역의 임의의 공간(5680
번지)을 확보합니다. 5680
번지에 어떤 데이터를 저장해야 하는지 읽습니다.
여러 개의 속성(property
, 프로퍼티)으로 이뤄진 데이터 그룹(Object
, 오브젝트)입니다😮.
이 그룹 내부 속성들을 모두 저장하기 위해5680
번지의 변수 영역을 별도로 마련합니다.
그 영역의 주소(7000
번지~)를5680
번지의 값으로 복제해 저장합니다. (객체의 프로퍼티를 저장하기 위한 메모리 영역은 그때그때 동적으로 확보합니다)7000
번지와7001
번지에 각각color
와price
라는 프로퍼티 이름을 지정합니다. 데이터 영역에서"red"
가 이미 있는지 검색하고, 없으면 데이터 영역에"red"
를5680
번지에 저장합니다. 이 주소(5680
번지)를7000
번지(식별자:color
)에 복제해 저장합니다. 숫자1000
역시 기존 데이터에 없으면5681
번지에 저장하고5681
을7001
번지(식별자:price
)의 값에 복제해 저장합니다.
참조형 데이터는 기본형 데이터와 다르게 '객체의 변수(프로퍼티) 영역'이 별도로 존재합니다. apple이라는 객체가 별도로 할애한 영역은 변수 영역이고 '데이터 영역'은 기존의 메모리 공간을 활용해 '주솟값'만 참조하고 있습니다. 즉, 데이터 영역에 저장된 값은 언제나 변하지 않습니다. 하지만 apple의 데이터 영역이 가리키는 주소(apple의 변수 영역)의 값은 언제든 바뀔 수 있습니다. 그렇기 때문에 참조형 데이터는 변할 수 있고, 가변 값이라 합니다.
왜 이러는 걸까요? 변수 영역에 값을 직접 대입하지 않고.
데이터 변환을 자유롭게 할 수 있게 함과 동시에 메모리를 더욱 효율적으로 관리하기 위한 고민의 결과이다. - 7p
변수 영역에 확보된 공간 내에서만 데이터 변환을 할 수 있다면 변환한 데이터를 다시 저장하기 위해 '확보된 공간을 변환된 데이터 크기에 맞게 늘리는 작업'이 선행되어야 합니다. 해당 변수 영역의 공간을 늘려야 하는데 그 공간 앞 뒤로 중요한 메모리가 실려있다면 어떡할까요? 공간을 늘리지 못하거나 중요한 메모리를 다른 곳으로 모두 옮기고 해당 변수 영역의 공간을 늘려야 합니다. 번거롭고, 비효율적입니다. 컴퓨터가 처리해야 할 연산이 많아지고 비용이 높아집니다. 결국 자바스크립트 개발자(?) 또는 이 저장 방식을 개발한 사람은, 효율적으로 데이터의 변환을 처리하려면 변수와 데이터를 별도의 공간에 나눠 저장하는 것이 최적이라고 생각했던 것입니다.
참고
'프로그래밍-학습기록 > Javascript' 카테고리의 다른 글
클로저는 글로 적기 글렀어. (0) | 2021.02.15 |
---|---|
자바스크립트 콜백 함수 이해하기 (0) | 2021.02.13 |
[Javascript] 다양한 상황에서 this는 무엇을 가리킬까 (0) | 2021.02.12 |
자바스크립트에서 실행 컨텍스트(execution context)가 도대체 뭐하는 애에요 (0) | 2021.02.10 |
javascript 논리연산자(&&, ||) 우선순위 vs. 단락 평가(short circuit) (0) | 2021.01.29 |