데이터타입- 원시타입과 객체타입의 차이 : 값에 의한 전달? 참조에 의한 전달?
1. 원시타입과 객체타입
자바스크립트의 데이터타입은 크게 원시타입과 객체타입으로 나눌 수 있다. 오늘은 원시타입과 객체타입의 차이점을 살펴볼 것이기 때문에 세부적인 데이터 타입에 대해서는 다루지 않으려고 한다.
1.1. 원시타입
숫자(Number), 문자열(String), 불리언(Boolean), undefined, 심벌(symbol), null 로 총 여섯개이다.
1.2. 객체타입
객체, 함수, 배열 등이다. 사실 객체는 원시타입을 제외한 모든 것들이다. 따라서 굉장히 큰 범위이나, 대표적으로 언급한 세가지가 있다.
2. 원시타입과 객체타입의 차이점
가장 큰 차이점은 값의 변경이 가능한지 여부이다. 원시타입은 '변경불가한 값'이다. 객체타입은 '변경가능한 값'이다.
또한 값을 할당할 때, 원시타입은 원시값(실제 값)이 저장되며, 이 원시타입 변수를 다른 변수에 할당할 때도 원시값이 복사되어 전달이 된다. 이것을 '값에 의한 전달(pass by value)' 라고 한다.
하지만 객체타입은 값을 할당할 때 참조값이 저장되며, 이 객체타입 변수를 다른 변수에 할당할 때도 참조값이 복사되어 전달이 된다. 이것을 '참조에 의한 전달(pass by reference)' 라고 한다. (사실은 객체타입 또한 값에 의한 전달이 일어나지만 이후 자세하게 설명하겠다)
이렇게만 보면 당최 무슨 말인지 이해가 안될 것이다. 위 글은 요약본이니 일단 아래 설명을 끝까지 다 본 후에 다시 읽을 것을 권장한다.
3. 값 할당 방식
3.1. 원시타입의 값 할당 방식
원시타입은 변수에 값을 할당할 때 실제값이 저장된다고 하였다. 예를 들면 score라는 변수에 70이라는 값을 할당하면 70이라는 실제값이 메모리 공간에 저장된다. 아래 그림을 보면 데이터 저장 방식을 볼 수가 있다.
왼쪽 그림을 보면 num1이라는 변수를 선언하고, 70이라는 값을 할당했다. 그러면 메모리 주소 안에 실제값 70으로 저장이 된 것을 알 수 있다. (주소는 임의의 값을 설정했다)
오른쪽 그림을 보면 원시값은 값을 변경할 수 없고 값의 재할당만이 가능하므로 100으로 재할당을 했다. 이때 메모리 상에는 새로운 주소에 변수값이 재할당 된다. 따라서 let num1의 메모리 주소가 바뀐 것을 알 수 있다.
그렇다면 여기서 다른 변수에 num1을 할당해주면 어떻게 될지 생각해보자. 새로운 변수는 복사하려는 값의 메모리 주소를 통해서 100이라는 값을 알아낸다. 그런다음에 새로운 변수의 메모리 주소에 100을 복사해서 할당하게 된다. 따라서 당연히 메모리 주소도 다르다. 이 방식은 값이 그대로 전달되기 때문에 '값에 의한 전달(pass by value)' 이라고 한다.(사실 원시값도 값이 전달되는 것이 아니라 엄밀히 따지자면 주소가 전달되는데 그걸 통해 값에 접근할 수 있다는 말이다)
위 그림은 원시값이 할당된 변수를 다른 변수에 할당할 때 어떻게 작동하는지 볼 수 있다.
처음에 num1 이라는 변수에 100이라는 원시값을 할당하였다. 그러면 메모리에서는 100이라는 실제값으로 저장이 된다. 이제 num1을 num2라는 변수에 할당하게 되면 num1의 주소를 통해 100이라는 실제값을 그대로 가져오게 된다. 물론 두 변수는 다른 메모리 주소값을 가진다.
3.2. 객체타입의 값 할당 방식
객체타입은 변수에 값을 할당할 때 참조값이 저장된다. 참조값이란 메모리 영역의 주소값이다. 즉, 객체타입의 값이 저장된 주소를 전달해주는 것이다. 다음 그림을 통해 더 자세히 설명하도록 하겠다.
왼쪽 그림은 num1이라는 변수에 객체를 할당한 모습이다. 변수에 객체를 할당하게 되면 메모리에는 그 자체의 실제값이 저장되는게 아니라 객체로 가는 주소값을 갖게 된다. 이것을 참조값이라고 한다. 그래서 변수 안에 저장된 메모리 주소와 객체의 메모리주소가 동일한 것을 확인할 수 있다.(파란색 글씨) 변수는 객체의 메모리 주소를 통해 객체를 참조하여 접근할 수 있다.
오른쪽 그림은 동일한 num1 변수에 할당한 객체 값을 변경했을 때의 작동 방식이다. 객체값은 원시값과 달리 그 자체로 변경 가능한 값이다. 그래서 따로 재할당을 해줄 필요가 없이 자체적으로 값을 변경할 수 있다. 따라서 객체값을 변경하면 메모리 주소는 변하지 않는 것을 확인할 수 있다.
위 그림은 객체값이 할당된 변수를 다른 변수에 할당할 때 어떻게 작동하는지 볼 수 있다.
처음에 num1이라는 변수에 객체를 할당하였다. 그리고 나서 num2라는 새로운 변수에 num1을 할당하였다. 그러면 변수num1은 저장되어있는 참조값(주소값)을 num2라는 변수에게 전달해준다. 따라서 num1과 num2가 모두 동일한 객체를 가리키게(참조하게)된다. 또한 참조값은 변경되지 않는다. 이렇게 참조값을 전달해준다고 하여 '참조에 의한 전달(pass by reference)' 이라고 말한다. 또는 참조값을 공유한다고 해서 '공유에 의한 전달(call by sharing)' 이라고 부르기도 한다.
그런데 자바스크립트에서는 사실 '값에 의한 전달' 만 일어난다. '참조에 의한 전달'로 보이는 객체타입도 사실 값을 전달하고 있다. 그 값이 원시값이냐 참조값이냐의 차이이다. (반전!)