[JS] 자바스크립트의 데이터 타입

본 글은
정재남, 『코어 자바스크립트』, 위키북스(2019)의 1장 데이터 타입을 보고 정리한 글입니다.
보다 자세한 정보를 원하시면 해당 도서를 읽어보시는 것을 추천드립니다.

자바스크립트 데이터 타입의 종류

자바스크립트의 데이터 타입에는 크게 원시형과 참조형이 있다.
원시형에는 number, string, boolean, null, undefined 등이 있고,
참조형에는 object, Array, Function, Date, RegExp 등이 있다.

구분 기준

일반적으로 원시형은 할당이나 연산시 복제되고, 참조형은 참조된다고 알려져 있지만,
엄밀하게 말하면 둘 모두 복제가 되기는 한다.
다만,

원시형은 값이 담긴 주솟값을 바로 복제하는 반면,
참조형은 값이 담긴 주소값들로 이루어지는 주솟값을 복제한다는 점이 다르다.

변수 선언과 데이터 할당

식별자와 변수

  • 변수 - 변할 수 있는 수, 그러나 반드시 '숫자'여야 하는 것은 아니다. 컴퓨터 용어에서 변수(variable)은 '변할 수 있는 무언가'를 뜻하는데, 여기서 무언가는 데이터를 말한다. 숫자, 문자열, 객체, 배열 모두 데이터이다.
  • 식별자 - 식별자라는 말은 어떤 데이터를 식별하는데 사용하는 이름, 즉 변수명을 뜻한다.

변수 선언

// 1.
var name;  // 변수 선언
name = "kimdaeseong"; // 변수 name에 "kimdaeseong"이라는 문자열 데이터 할당

// 2.
var name = "kimdaeseong"; // 변수 선언과 할당을 한 문장으로 표현

여기서 1번과 2번에 대해 자바스크립트 엔진은 같은 동작을 수행한다.

메모리에서 비어있는 공간 확보 -> 그 공간의 이름을 설정(선언) -> name이라는 이름을 가진 주소를 검색해서 그 곳에 문자열 'kimdaeseong'을 할당

그런데 실제로는 해당 위치에 "kimdaeseong"을 직접 저장하지 않는다!!

데이터를 저장하기 위한 별도의 메모리 공간을 다시 확보해서 "kimdaeseong"을 저장하고, 그 주소를 변수 영역에 저장한다고 한다.

이 책의 저자분께서는 해당 내용의 이해를 돕기 위해 '변수 영역'과 '데이터 영역'으로 데이터 성질을 구분해서 설명하는데, 이해에 도움이 되기 때문에 본 글에서도 이 방식을 가져오도록 하겠습니다.

이 할당 과정을 설명하면

  1. 변수 영역에서 빈 공간(@1003)을 확보
  2. 확보한 공간의 식별자를 name으로 지정
  3. 데이터 영역의 빈 공간(@5004)에 "kimdaeseong"을 저장
  4. 변수 영역에서 name이라는 식별자를 검색한다(@1003).
  5. 앞서 저장한 문자열의 주소(@5004)를 @1003의 공간에 대입

이렇게 직접 대입하지 않고 주소를 이용하여 한단계를 더 거치는 이유

데이터 변환의 자유로움 - 확보된 공간 내에서만 데이터 변환을 할 수 있다면 변환 데이터를 다시 저장하려면 확보된 공간을 데이터 크기에 맞추어 늘리는 작업이 필요

원시형 데이터와 참조형 데이터

원시형 데이터는 불변값이고, 참조형 데이터는 가변값이다. 그런데, 많은 사람들이(사실 나만...?) 변수와 상수의 구분과 불변값과 가변값의 구분에 대해 혼란스러워 할 것이라고 생각한다. 예를 들어,

var, let은 가변값이고, const는 불변값?!
(완전히 틀린 말이다.)

우선 변수와 상수의 개념과 불변값과 가변값의 개념부터 이해하고, 그 다음에 원시형과 참조형 데이터의 불변성에 대해서 이야기해보도록 하겠다.

변수와 상수

"변경 가능성"으로 구분한다.
바꿀수 있으면 변수(Variable)
바꿀수 없으면 상수(Constant)

변수와 상수를 구분짓는 변경 가능성의 영역은 변수 영역에서 정해진다!
-> 즉, 데이터 할당이 이루어진 변수 공간에 다른 데이터를 재할당할 수 있는지에 대한 문제

var a = "abc"
a = "def" // 문제없음
// var이 variable의 줄임말

const a = "abc"
a = "def" // TypeError: Assignment to constant variable.
// const가 constant의 줄임말

불변값과 가변값

변수와 상수의 구분과 달리
불변값과 가변값의 구분은
데이터 영역에서의 "변경 가능성"으로 판단

불변값

예를 들어,

var a = "Abc"

현재 변수 영역 a에 데이터 영역 "abc"의 주소가 값으로 등록되어 있는 상태에서

a = "Abcedfg"

로 재할당을 한다고 하면 데이터는

데이터 영역의 @5004의 데이터가 변하는 것이 아니라, 새롭게 @5005에 추가된 녀석으로 새롭게 할당되는 것이다.
마치 변수 a의 값이 변화되는 것 처럼 보이지만!
불변값과 가변값의 구분은 데이터 영역에서 판단하는 것이므로, 사실 변화한 것이 아니라 완전히 새로운 데이터를 추가하는 것이다.

여기서 기억해야할 점은,

  • 한번 만든 값(데이터 영역)에서 만든 값은 가비지 컬렉팅을 당하지 않는 한 영원히 변화하지 않는다!!!
  • 원시형 데이터는 모두 불변성을 지닌다.(변화하는 것이 아니라 새로운 값을 만들어서 재할당하는 것뿐)

이라고 할 수 있는데.... 가비지 컬렉팅이라는 새로운 내용이 나온다.

가비지 컬렉팅

프로그래밍에서의 메모리 관리

프로그래밍에서 메모리의 생존주기는 프로그래밍 언어와 관계없이 비슷하다고 한다.

  1. 필요할 때 할당한다.
  2. 사용한다. (읽기, 쓰기)
  3. 필요없어지면 해제한다.

2번은 모든 언어에서 명시적으로 사용되지만, 1번과 3번은 저수준 언어에서는 명시적이며, 자바스크립트와 같은 대부분의 고수준 언어에서는 암묵적으로 작동한다.
(땡큐!!!!!!!!!!)


위의 예시를 다시 한번 가져와 보았다. 변수 a에 "Abcedfg"를 재할당하게 되면서 데이터 영역에 @5004("Abc")는 어디에도 할당되어 있지 않다. 즉, 데이터 영역의 메모리를 차지하고 있지만, 어떤 다른 메모리도 @5004를 참조하지 않는다.

-> 이렇게, 어떤 다른 메모리도 참조하지 않는 메모리를 가비지라고 부르며, 그것을 자바스크립트의 가비지 컬렉터가 특정 알고리즘으로 일정 주기마다 수집하고, 할당된 메모리를 해제하는 것이다.
이것에 대해 더 궁금하신 분은 MDN으로...

가변값

원시형 데이터들은 모두 불변값이다.
그렇다면 참조형 데이터 타입은 가변값일까?
기본적인 성질은 가변값이지만, 설정에 따라 변경 불가능한 경우도 있고, 아예 불변값으로 활용하는 방안도 있다.

이쯤에서 다시 한번 짚고 넘어가자면,

불변성과 가변성을 나누는 것은 데이터 영역에서의 변경 가능성이다.

이걸 기억하면서, 실제 객체가 어떤식으로 메모리에 저장되는지 살펴보자.

객체의 생성 및 할당
let obj = {
  a: "abc"
  b: 123
}

이라는 객체는,

이렇게 저장되게 된다.
원시형 데이터 타입과 가장 차이나는 점은

객체의 변수 영역이 별도로 존재한다는 점이다.

객체의 프로퍼티마다 객체의 변수 영역에 값들이 저장되는 것이다. 하지만, a : "abc", b : 123 이 두개 모두 각각 string과 number 의 원시형 데이터 타입이기 때문에 데이터 영역에 저장되었다.
즉, 객체 @5001의 변수 영역에 여러개의 데이터 그룹이 저장된 것이다.

여기서 변수에 얼마든지 다른 값을 대체할 수 있기 때문에 가변성이라고 말할 수 있는 것이다.

원시형 데이터와 참조형 데이터의 복사

위에서 보여준 방식대로 데이터를 저장하기 때문에, 원시형 데이터를 복사하고 값을 변경할때와 참조형 데이터를 복사하고 값을 변경할때에는 차이점이 발생할 수 밖에 없다. 실제 상황을 가정하고 그때 데이터가 어떻게 저장할 수 있는지 확인해보자!

var a = 10;
var b = a;
var obj1 = {c:10, d: "ddd"}
var obj2 = obj1
// 상호 복사

b = 15;
obj2.c = 20;
// 값 변경

위 코드를 그대로 옮기면 다음과 같다.

  1. 원시형 데이터 - 변수 a의 값을 복사했던 b에 새롭게 값을 할당하면서 데이터 영역에 @5004에 새로운 데이터가 추가되고 그 주소를 참조한다. 결국 a와 b는 다른 주소를 바라보게 되었다.
  2. 참조형 데이터 - 변수 obj1의 값을 복사했던 obj2인데, 여기서 obj1의 값 자체가 @5002라는 주소이다. 그런데 이 @5002 데이터 영역은 가변값이고, obj2.c의 값을 변경한다는 것은 객체 @5002의 변수영역을 변경하기 때문에 결국 복사를 하더라도 여전히 같은 객체를 바라본다.
a !== b
obj1 === obj2

좋은 웹페이지 즐겨찾기