많은 마블 덕후들이 기다리던 영화 "캡틴 아메리카: 시빌워"가 지난 4월 27일에 개봉하였습니다. 영화 내용을 모르는 분들을 위해 간단하게 스토리를 얘기하면 어벤져스와 관련된 사고로 부수적인 피해가 발생하자 정부에서는 어벤져스 맴버를 관리.감독하는 "슈퍼 히어로 등록제" 시스템을 내놓게 됩니다. 이에 어벤져스 내부에서는 정부 입장을 지지하는 팀 아이언맨과 정부 개입없이 자유로운 활동을 해야 한다는 팀 캡틴으로 나뉘어 대립하게 됩니다.
서로 다른 능력을 갖고 있는 자바스크립트의 데이터 타입들도 비슷한 성향을 갖고 있는 2개 그룹으로 구분할 수 있습니다. 하나는 값을 복사할 수 있는 Primitive Type ( 원시 타입 ), 다른 하나는 값을 참조하는 Reference Type ( 참조 타입 ) 입니다.
( 물론 영화 "캡틴 아메리카:시빌 워" 처럼 서로 싸우는 일은 없습니다. ^^;;; )
이번 장에서는 Primitive Type과 Reference Type이 각각 어떠한 특징을 갖고 있는 살펴보겠습니다.
앞서 #3. 변수 편에서 변수를 선언한다는 것은 "변수명이라고 하는 박스 안에 데이터를 넣는다" 라고 설명했는데, 참조 타입에 적용하기에는 무리가 있기 때문에 이번 연재글에서는 잠시 이 문구를 잊어주시기 바랍니다.
Primitive Type 은 변수에 있는 값이 복사되어 다른 변수에 저장되는 것을 의미합니다. 조금 개발스럽게 얘기한다면 메모리에 있는 값을 복사하는 형태입니다. 아래는 변수 str2 의 값으로 String 데이터 타입을 갖고 있는 변수 str1 이 들어있는 예제 코드입니다.
var str1 = "Hello World";
var str2 = str1;
console.log(str2) // "Hello World" 출력
여기서 변수 str1 의 값을 다음과 같이 바꾸면 str2 는 어떤 값을 취하게 될까요?
str1 = "Nice to meet you";
console.log(str2);
느낌상으로는 변수 str1 의 값이 달라졌기 때문에 str1 을 값으로 받고 있는 str2 의 값 또한 달라져야 하는 것이 아닌지 생각할 수 있습니다. 하지만 실제 결과값을 보면 str2 는 "Hello World" 갖고 있는 것을 확인할 수 이습니다.
위와 같은 결과 값이 나오는 이유는 Primitive Type 은 데이터를 복사하여 전달하기 때문에 원본 데이터가 변경되었다고 해서 복사된 데이터에 영향을 받지 않습니다.
즉, Ctrl + C, Ctrl + V 와 같은 성격을 갖고 있는 것이 Primitive Type 이며, Number, String, Undefined, Null 등이 Primitive Type 의 종류에 속합니다.
Reference Type 은 "Reference" 단어가 주는 모호함때문에, 처음 필자가 Reference Type 이해하는데 생각보다 긴 시간이 걸렸습니다. Reference Type 의 특징을 제대로 이해하지 못하고 넘어가면 이후 자바스크립트의 다른 주요 개념들을 학습하는데 문제가 될 수 있으니 꼭 숙지하시기 바랍니다. 먼저 "참조"가 갖고 있는 사전적 의미를 살펴보겠습니다.
참조 : 관련된 사항을 비교하고 대조하여 살펴보는 것을 의미한다.
필자의 경우에는 개발에서는 "참조" 라는 단어의 사전적 의미를 그대로 사용했을 때 개념을 이해하는데 혼란이 왔었습니다. 대신 "참조" 를 "가르킨다" 라고 다시 표현하니 그제서야 Reference Type 의 특징을 정확하게 이해할 수 있었습니다. 예제를 보면서 이 부분에 대해서 다시 설명드리겠습니다.
아래는 변수 obj2 의 값으로 Object 데이터 타입을 갖고 있는 변수 obj1 이 들어있는 예제 코드입니다. 여기서 var obj1 = { name : "Kim Dong Woo" } 코드를 정확하게 해석하면, 변수 obj1 안에 { name : "Kim Dong Woo" } 값이 들어있는 것이 아니라 변수 obj1 은 { name : "Kim Dong Woo" } 을 가르키고 있다(참조하고 있다)고 해석해야 합니다.
var obj1 = { name : "Kim Dong Woo" };
var obj2 = obj1;
console.log(obj2) // {name: "Kim Dong Woo"} 출력
다시 var obj2 = obj1 코드를 해석하면 변수 obj2 안에 변수 obj1 의 값이 들어있는 것이 아니라 변수 obj2 은 변수 obj1 이 가리키고 있는 { name : "Kim Dong Woo" } 을 가르키고 있다고 해석해야 합니다. 그렇기 때문에 obj2 은 자신이 가르키고 있는 { name : "Kim Dong Woo" } 을 출력하게 됩니다.
여기서 obj1.name 값을 변경하면 obj1 이 가르키고 있는 { name : "Kim Dong Woo" } 이 변경되기 때문에 이를 가리키고 있던 obj2 에게도 영향을 미쳐 변경된 { name : "Lee Ho" } 값이 출력됩니다.
저는 Reference Type 의 특징이 이해됐을 때, 영화 "사랑과 영혼" 에서 패트릭 스웨이지의 영혼이 사기꾼 점성술사 우피 골드 버그의 육체에 빙의하여 데미 무어와 함께 춤을 추는 장면이 생각났습니다. 이 장면에서 변수 obj1 은 살아있는 패트릭 스웨이지의 육체, { name : "Kim Dong Woo" } 은 패트릭 스웨이지의 영혼, obj2 는 패트릭 스웨이지의 영혼이 빙의된 우피 골드 버그의 육체로 볼 수 있습니다.
위에서 설명한 내용을 그림으로 정리하면 아래와 같습니다.
이런 Reference Type 특징을 갖고 있는 데이터 타입으로는 Array, Object, Function 등이 있습니다.
앞에서 설명한 Primitive Type 과 Reference Type 의 특징은 비교 연산자를 사용하면 보다 명확하게 이해할 수 있습니다.
먼저 Primitive Type 의 경우 같은 값을 갖고 있는 str1, str2 을 비교하면 예상한대로 true 가 결과값으로 반환되는 것을 확인할 수 있습니다.
문제(?)가 되는 것은 Reference Type 입니다. ^^;;
obj1 과 obj2 를 비교한 결과값을 살펴보면 false 가 출력됩니다. 이것을 육체와 영혼의 개념으로 다시 설명하면, { name : "Kim Dong Woo" } 는 하나의 영혼이 아니라 겉모습이 비슷한 서로 다른 { name : "Kim Dong Woo" } 영혼이 2개 존재하는 것입니다.
즉, obj1 과 obj2 는 서로 다른 영혼이 빙의되어 있는 상태이며, 서로 다른 영혼을 비교하고 있기 때문에 false 가 출력되는 것입니다.
글을 쓰다보니 이번 연재 내용의 대부분을 Reference Type 을 설명하는데 할애했네요. Primitive Type 은 직관적으로 판단하기 쉽기 때문에 빠르게 받아들일 수 있지만, Reference Type 은 "참조" 라는 단어가 주는 모호성때문에 초반에 개념을 이해하는데 약간의 장애가 될 수 있을 것 같아 공을 들여 설명했습니다.
다음 장에서는 데이터 타입이 어떤 능력 ( property 와 method )을 갖고 있는지 살펴보겠습니다.