Data Type
목차
데이터 타입의 종류
Primitive type
- Number
- String
- Boolean
- null
- undefined
- Symbol (ES6 추가)
Reference type
- Object
- Array
- Function
- Date : 날짜
- RegExp : 정규표현식
- Map, WeakMap (ES6 추가)
- Set, WeakSet (ES6 추가)
기본형과 참조형의 구분
일반적으로 기본형은 할당이나 연산시 복제되고 참조형은 참조된다고 한다. 하지만 엄밀히 말하면 둘 모두 복제되는 것으로, 기본형은 주솟값이 담긴 주솟값을 바로 복제하는 반면 참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제한다는 차이가 있다.
데이터 타입에 관한 배경지식
1. 메모리와 데이터
컴퓨터는 모든 데이터를 0 또는 1로 바꿔 표현하는 메모리 조각 bit
를 사용하고 각 비트는 고유한 식별자(unique identifier)를 통해 위치를 확인할 수 있다. 하지만 비트 단위로 위치를 확인하면 매우 비효율적이므로 몇 개씩 묶어 하나의 단위로 만들어 표현할 수 있는 값도 늘어나면서 검색 시간을 줄이기 위해 byte가 생겨났다.
많은 비트를 한 단위로 묶으면 검색 시간도 줄이고 표현할 수 있는 데이터의 개수도 늘어나겠지만 동시에 낭비되는 비트가 발생한다. 이러한 낭비를 최소화하기 위해 C/C++, 자바 등의 정적 타입 언어는 데이터 타입별로 메모리 영역을 2 bytes, 4 bytes 등으로 나누어 정해놓았다.
반면 JavaScript의 경우 메모리 용량이 과거보다 월등히 커진 상황에서 등장하여 메모리 압박이 적었고 숫자의 경우 C에서 short, int, longlong 등으로 구분하는 것과 달리 JS에서는 8 bytes를 확보한다.
정리하자면 모든 데이터는 바이트 단위의 식별자 메모리 주솟값(memory address) 을 통해 서로 구분하고 연결할 수 있다.
2. 식별자와 변수
변수(variable)와 식별자(identifier)를 혼용해서 사용하는 경우가 많다.
대부분의 경우 문맥에 따라 정확히 무엇을 말하고자 하는지 유추할 수 있기 때문에 문제없지만 둘의 차이를 정확히 모른다면 혼란 스러울 수 있다.
-
변수(variable) : "변할 수 있는 무언가"
컴퓨터에서 변할 수 있는 무언가란 데이터를 의미하고 변수는 즉 데이터 자체를 말한다.
-
식별자(identifier) : "사용하는 이름"
어떤 데이터를 식별하는데 사용하는 이름, 즉 변수명을 의미한다.
변수 선언과 데이터 할당
1. 변수 선언
변수 선언에 관한 것은 Web/basic 에서 다루었다. 여기서는 방법이 아닌 동작 원리를 알아본다.
var a;
을 말로 풀어쓰면 변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 a로 한다 가 된다. 변수란 변할 수 있는 데이터이니 선언할 때 undefined
이더라도 나중에 다른 값으로 바꿔 줄 수가 있다.
결국 변수란 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇이라고 생각할 수 있겠다.
2. 데이터 할당
위와 같이 변수를 선언해주면 메모리 영역에 다음과 같이 데이터가 저장될 것 이다.(간략히 표현)
주소 | ... | 1002 | 1003 | 1004 | ... |
---|---|---|---|---|---|
데이터 | 이름: a 값: |
여기서 다음과 같이 변수에 데이터를 할당해주면 어떻게 될까
var a; // 변수 a 선언
a = "abc"; // 변수 a에 데이터 할당
var a = "abc"; // 변수 선언과 할당을 한 문장으로 표현
변수 선언과 할당을 위와 같이 두 문장으로 명령하든, 아래와 같이 한 문장으로 명령하든 JavaScript 엔진은 결국 같은 동작을 수행한다.
그리고 그 과정은 아마도 변수 선언에서와 같이 메모리 공간을 확보하고 이름을 a로 선언해준 후 그 값에 abc
를 할당해주면 될 것 같다.
하지만 실제로는 값에 바로 문자열 abc
를 저장하지는 않는다. 실제로는 데이터를 저장하기 위한 별도의 메모리 공간을 다시 확보해서 문자열 abc
를 저장하고 그 주소를 변수 영역의 값:
에 저장하는 식으로 이루어진다.
-
변수 영역
주소 ... 1002 1003 1004 ... 데이터 이름: a
값: @5004 -
데 이터 영역
주소 ... 5002 5003 5004 ... 데이터 abc
- 변수 영역에서 빈 공간(@1003)을 확보한다.
- 확보한 공간의 식별자를 a로 지정한다.
- 데이터 영역의 빈 공간(@5004)에 문자열
abc
를 저장한다. - 변수 영역에서 a라는 식별자를 검색한다(@1003)
- 앞서 저장한 문자열의 주소(@5004)를 @1003의 공간에 대입한다.
데이터 영역을 분리하는 이유
JavaScript는 Number 데이터에 대해 8 bytes 의 공간을 확보한다고 하였다. 반변 String 에 대해서는 정해진 규격이 없다.
글자는 영어의 경우 1 byte, 한글의 경우 2 bytes 로 글자 하나당 용량도 다르고 길이가 얼마나 될지 알 수 없기 때문에 확보한 공간에서만 데이터 변환을 할 수 있다면 데이터가 클 경우 '확보된 공간을 변환된 데이터 크기에 맞게 늘리는 작업'이 선행돼야 할 것이다.
따라서 효율적으로 문자열 데이터의 변환을 처리하기 위해 데이터를 별도의 공간에 나누어 저장한다.
이번엔 문자열 abc
에 def
를 추가해보자 컴퓨터는 abc
가 저장된 공간에 abcdef
를 할당하지 않고 새로운 공간에 abcdef
라는 문자열을 새로 만들어 그 주소를 변수 공간에 연결한다.
-
변수 영역
주소 ... 1002 1003 1004 ... 데이터 이름: a
값: @5004 -
데이터 영역
주소 ... 5003 5004 5005 ... 데이터 abc
abcdef
이렇게 새로운 공간을 만들어주며 저장하면 비효율적으로 보일 수 있다 다음 예를 보자
500개의 변수 공간이 있고 모든 변수에 숫자 5를 할당해야 한다. 이 때는 데이터 할당이 어떤 식으로 이루어질까?
만약 각 변수마다 숫자 5데이터를 만들어서 할당하려고 하면 숫자형은 8 bytes가 필요하므로 총 500 * 8 = 4000
bytes가 필요할 것이다. 하지만 데이터를 하나의 영역에 저장해주고 각 변수에 그 데이터 영역의 주소를 입력한다면 500 * 2 + 8 = 1008
bytes 만 필요하게 된다. 이처럼 변수 영역과 데이터 영역을 분리하면 중복된 데이터에 대한 처리 효율이 높아진다.