JavaScript 데이터 타입 4편

김예진·2021년 2월 11일
0

Core JavaScript

목록 보기
4/7
post-thumbnail

코어 자바스크립트 책의 1장 데이터 타입 내용을 정리한 글이다.

기본형 데이터와 참조형 데이터

불변값

변수(variable)상수(constant)를 구분하는 성질은 변경 가능성이다. 불변값상수를 같은 개념으로 오해하기 쉬운데, 이 둘은 명확히 구분할 필요가 있다. 변수상수를 구분 짓는 변경 가능성의 대상은 변수 영역의 메모리이다. 한번 데이터 할당이 이루어진 변수 공간에 다른 데이터를 재할당할 수 있는지 여부가 관건이다. 반면 불변성 여부를 구분할 때의 변경 가능성의 대상은 데이터 영역 메모리이다.

기본형 데이터인 숫자, 문자열, boolean, null, undefined, Symbol은 모두 불변값이다. 그 중 숫자를 예로 들어 불변성의 개념을 알아보자.

var a = 5;
a = 7;

변수 a에 숫자 5를 할당했다. 그러면 컴퓨터는 일단 데이터 영역에서 5를 찾고, 없으면 그제서야 데이터 공간을 하나 만들어 저장한다. 그 주소를 a의 값으로 저장한다.

이후 변수 a의 값을 7로 바꾸고자 한다. 그러면 기존에 저장된 5 자체를 7로 바꾸는 것이 아니라 기존에 저장했던 7을 찾아서 있으면 재활용하고, 없으면 새로 만들어 a에 저장한다. 결국 5와 7 모두 다른 값으로 변경할 수 없다.

이처럼 문자열 값도 한 번 만든 값을 바꿀 수 없고, 숫자 값도 다른 값으로 변경할 수 없다. 변경은 새로 만드는 동작을 통해서만 이루어진다. 이것이 바로 불변값의 성질이다. 한 번 만들어진 값은 가비지 컬렉팅을 당하지 않는 한 영원히 변하지 않는다.

가변값

기본형 데이터는 모두 불변값인데 그렇다면 참조형 데이터는 모두 가변값일것 같은 생각이 든다. 기본적인 성질은 가변값인 경우가 많지만 설정에 따라 변경 불가능한 경우도 있고, 아예 불변값으로 활용하는 방안도 있다. 우선 참조형 데이터를 변수에 할당하는 과정부터 살펴보자.

var obj = {
  a: 1,
  b: 'bbb'
};

변수 영역

주소1001100210031004···
데이터이름: obj
값:@5001

데이터 영역

주소5001500250035004···
데이터@7103 ~ ?1'bbb'

객체 @5001의 변수 영역

주소7103710471057106···
데이터이름: a
값:@5003
이름: b
값:@5004

참조형 데이터를 변수에 할당하는 과정은 다음과 같다.

  1. 우선 컴퓨터는 변수 영역의 빈 공간(@1002)를 확보하고, 그 주소의 이름을 obj로 지정한다.
  2. 임의의 데이터 저장 공간(@5001)에 데이터를 저장하려고 보니 여러 개의 프로퍼티로 이루어진 데이터 그룹니다. 이 그룹 내부의 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소(@7103 ~ ?)를 %5001에 저장한다. (객체의 프로퍼티들을 저장하기 위한 메모리 영역은 크기가 정해져 있지 않고 필요한 시점에 동적으로 확보한다.)
  3. @7103 및 @7104에 각각 ab라는 프로퍼티 이름을 지정한다.
  4. 데이터 영역에서 숫자 1을 검색한다. 검색 결과가 없으므로 임의로 @5003에 저장하고, 이 주소를 @7103에 저장한다. 문자열 'bbb' 역시 임의로 @5004에 저장하고, 이 주소를 @7104에 저장한다.

기본형 데이터와의 차이는 **'객체의 변수(프로퍼티) 영역'이 별도로 존재한다**는 점이다. 표를 보면 객체가 별도로 할애한 영역은 변수 영역일 뿐 '데이터 영역'은 기존 메모리 공간을 그대로 활용하고 있다.

데이터 영역에 저장된 값은 모두 불변값이다. 그러나 변수에는 얼마든지 다른 값을 대입할 수 있다. 바로 이 부분 때문에 흔히 참조형 데이터는 불변(immutable)하지 않다(가변값이다)라고 하는 것이다.

프로퍼티를 재할당하는 예제로 확인해보자.

var obj = {
  a: 1,
  b: 'bbb'
};
obj.a = 2;

변수 영역

주소1001100210031004···
데이터이름: obj
값:@5001

데이터 영역

주소50015002500350045005···
데이터@7103 ~ ?1'bbb'2

객체 @5001의 변수 영역

주소7103710471057106···
데이터이름: a
값:@5005
이름: b
값:@5004

obja 프로퍼티에 숫자 2를 할당하려고 한다. 데이터 영역에서 숫자 2를 검색한다. 검색 결과가 없으므로 빈 공간인 @5005에 저장하고, 이 주소를 @7103에 저장한다. 변수 obj가 바라보고 있는 주소는 @5001로 변하지 않았다. 즉 '새로운 객체'가 만들어진 것이 아니라 기존의 객체 내부의 값만 바뀐 것이다.

변수 복사 비교

동작 방식을 알았으니 이제 기본형 데이터와 참조형 데이터의 차이를 확인해보자.

먼저 변수를 복사할 때의 변화를 살펴보자.

var a = 10;
var b = a;

var obj1 = { c: 10, d: 'ddd' };
var obj2 = obj1;

변수 영역

주소1001100210031004···
데이터이름: a
값:@5001
이름: b
값:@5001
이름: obj1
값:@5002
이름: obj2
값:@5002

데이터 영역

주소5001500250035004···
데이터10@7103 ~ ?'ddd'

객체 @5002의 변수 영역

주소7103710471057106···
데이터이름: c
값:@5001
이름: d
값:@5003

우선 기본형 데이터부터 살펴보자.

  1. 변수 영역의 빈 공간 @1001을 확보하고 식별자를 a로 지정한다.
  2. 숫자 10을 데이터 영역에서 검색하고 없으므로 빈 공간 @5001에 저장한다.
  3. 이 주소를 @1001에 넣는다.

이렇게 a에 대한 변수 선언 및 할당이 종료되고 이제 복사를 할 차례이다.

  1. 변수 영역의 빈 공간 @1002를 확보하고 식별자를 b로 지정한다.
  2. 식별자 a를 검색해 그 값을 찾아와야 하는데, @1001에 저장된 값인 @5001을 @1002에 값으로 대입한다.

다음으로 참조형 데이터이다.

  1. 변수 영역의 빈 공간 @1003을 확보해 식별자를 obj1로 지정한다.
  2. 데이터 영역의 빈 공간 @5002를 확보하고, 데이터 그룹이 담겨야 하기 때문에 별도의 변수 영역 @7103~을 확보해 그 주소를 저장한다.
  3. @7103에는 식별자 c를, @7104에는 식별자 d를 입력한 다음, c에 대입할 값 10을 데이터 영역에서 검색한다.
  4. @5001에 이미 저장돼 있으므로 이 주소를 @7103에 연결하고
  5. 문자열인 'ddd'는 데이터 영역의 빈 공간(@5003)에 새로 만들어 @7104에 연결한다.

이렇게 obj1에 대한 선언 및 할당 과정이 종료되고 이제 복사를 할 차례다.

  1. 변수 영역의 빈 공간 @1004를 확보하고 식별자를 obj2로 지정한다.
  2. 식별자 obj1을 검색해 그 값인 @5002를 @1004에 값으로 대입한다.

변수를 복사하는 과정은 기본형 데이터와 참조형 데이터 모두 같은 주소를 바라보게 되는 점에서 동일하다. 하지만 데이터 할당 과정에서 이미 차이가 있기 때문에 변수 복사 이후의 동작에 큰 차이가 발생한다.


var a = 10;
var b = a;

var obj1 = { c: 10, d: 'ddd' };
var obj2 = obj1;

b = 15;
obj2.c = 20;

변수 영역

주소1001100210031004···
데이터이름: a
값:@5001
이름: b
값:@5001
이름: obj1
값:@5002
이름: obj2
값:@5002

데이터 영역

주소50015002500350045005···
데이터10@7103 ~ ?'ddd'1520

객체 @5002의 변수 영역

주소7103710471057106···
데이터이름: c
값:@5005
이름: d
값:@5003

기본형 데이터를 복사한 변수 b의 값을 바꿨더니 @1002의 값이 달라진 반면, 참조형 데이터를 복사한 변수 obj2의 프로퍼티의 값을 바꿨더니 @1004의 값은 달라지지 않았다. 즉, 변수 ab는 서로 다른 주소를 바라보게 됐으나, 변수 obj1obj2는 여전히 같은 객체를 바라보고 있는 상태이다.

이를 코드로 표현하면 다음과 같다.

a !== b
obj1 === obj2

이 결과가 바로 기본형과 참조형 데이터의 가장 큰 차이점이다. 대부분의 자바스크립츠 책에서는 '기본형은 값을 복사하고 참조형은 주솟값을 복사한다'고 설명하고 있지만, 사실은 어떤 데이터 타입이든 변수에 할당하기 위해서는 주솟값을 복사해야 하기 때문에, 엄밀히 따지면 자바스크립트의 모든 데이터 타입은 참조형 데이터일 수밖에 없다. 다만 기본형은 주솟값을 복사하는 과정이 한 번만 이뤄지고, 참조형은 한 단계를 더 거치게 된다는 차이가 있다.



이번 편에서는 참조형 데이터를 변수에 선언하고 할당하는 과정, 그리고 변수를 복사한 이후 재할당하는 과정에서의 기본형과 참조형 데이터의 차이를 알아봤다. 다음 편에서는 불변 객체와 얕은 복사, 깊은 복사에 대해 알아볼 것이다.

0개의 댓글

관련 채용 정보