[Javascript] 원시 타입(Primitive Type)과 참조 타입(Reference Type)

hyeojung·2022년 1월 16일
1

Javascript

목록 보기
1/2
post-thumbnail
post-custom-banner

자바스크립트는 동적 타입(dynamic typed) 언어 혹은 느슨한 타입(loosely typed) 언어이며 구문 작성이 자유롭고 느슨하다고 전 포스팅에서 한 번 언급한 적이 있다. 예를 들면 이런 식이다.

const a = 12;
const b = "12";

위와 같이 코드를 작성했을 때, 따로 변수에 자료형을 지정해주지 않았지만 자바스크립트는 자동으로 a는 number 타입으로, b는 string 타입으로 인식한다.
그리고 이런 것도 가능하다.

console.log(a == b); // true
console.log(a === b); // false

첫번째 줄에서는 a와 b를 비교할 때 먼저 형변환을 통해 두 값의 자료형을 일치시킨 뒤 비교하는 동등 연산자(==, equality operator)를 사용했기 때문에 a와 b가 같다는 결과가 나온다.
하지만 두번째 줄에서는 데이터 타입의 변환 없이 비교하여, 타입의 동등 여부까지 검사하는 일치 연산자(===, strict equality operator)를 사용했기 때문에 a와 b가 다르다는 결과가 나온다.

이처럼 Javascript는 다른 언어(C, Java 등)들에 비해 자료형 즉 타입에 비교적 너그럽다.
이런 Javascript의 특성은 코드를 짤 때는 행복하게 느껴질 수도 있지만, 코드에서 오류가 발생했을 땐 지옥의 디버깅을 겪게 하는 악마로 느껴질 수도 있다.

그러므로 자바스크립트 내부에서 변수들의 타입이 어떻게 다루어지는지 이해하고 Typescript를 이용한 정적 타이핑을 한다면 보다 더 슬기로운 코딩생활을 할 수 있겠지? 🙂

그래서 이번 포스팅에서는 슬기로운 코딩생활을 위해 자바스크립트의 데이터 타입에 대해 알아보려고 한다 🙌🏻


🧩 원시 타입 (Primitive Type)

원시 타입에 속하는 데이터 타입에는 숫자(Number & Bigint), 문자열(String), 논리형(Boolean), null, undefined, 심볼(Symbol)이 있다.

참고로 NaN은 Not a Number라는 뜻으로 숫자에 속한다. null, undefined, NaN이 어떻게 다른지는 나중에 따로 포스팅해보도록 하겠다 !

✔️ 원시 타입의 불변성 (immutable)

자바스크립트에서 원시 타입은 변수에 할당될 때 메모리에 고정 크기로 원시 값을 저장하고 그 값을 변수가 직접 가리키는 형태를 띈다.

즉 데이터를 저장하기 위한 별도의 데이터 공간을 확보해 값을 저장하고, 그 공간을 변수 영역에 저장한다.
➡️ 변수 영역과 데이터 영역이 존재

이렇게 할당된 값은 불변성(immutable)을 갖는다.
즉 메모리에 할당된 원시 타입의 값은 그 자체가 변경될 수 없다.

이에 대해 조금 더 자세히 설명해 보자면, 변수에 값을 재할당할 때 기존 값이 변하는 것처럼 보이지만 사실은 새로운 메모리에 재할당한 값이 저장되고 변수가 가리키는 메모리가 달라지는 것이다.

위 사진을 통해, str에 "문자열"이라는 값을 할당한 후 "문자열2"라는 값을 재할당하면 새로운 메모리에 재할당한 값인 "문자열2"가 저장되고 변수가 그 메모리를 가리키게 되는 것을 알 수 있다.

✔️ 원시 타입의 값 복사하기

원시 타입의 변수들은 데이터 복사가 일어날 때 값이 담긴 주솟값을 바로 복사한다 ✨

var str1 = "hello";
var str2 = str1;

str1 = "world";

console.log(str1); // world
console.log(str2); // hello

위의 코드를 보면 알 수 있듯 원본 변수에 값을 재할당해도 복사본의 값은 변하지 않는다.

이것은 새로운 변수 str2에 str1을 복사할 때 str1의 값이 저장되어 있는 메모리 공간을 변수가 가리키도록 하기 때문이다.
그리고 str1에 다른 값인 "world"를 재할당하면 메모리 공간에 "world"가 새로 할당되고, str1은 "world"가 저장되어 있는 공간을 가리키게 된다.

즉 원시 타입의 값은 한 번 만들면 바꿀 수 없다. 이미 만들어진 값은 가비지 컬렉팅을 당하지 않는 이상 사라지지 않는다 !


🧩 참조 타입 (Reference Type)

자바스크립트에서 원시 타입을 제외한 나머지는 참조 타입(객체, Object)이라 할 수 있다.
객체의 하위 분류에 속하는 데이터 타입에는 배열(Array), 함수(Function), 날짜(Date), 정규표현식(RegExp) 등이 있다.

✔️ 참조 타입과 원시 타입의 차이점

참조 타입과 원시 타입의 가장 큰 차이점은, 객체의 변수(프로퍼티) 영역이 추가로 존재한다는 것이다.

예를 들어,

var obj1 = {
  a: 1,
  b: "bbb"
};

이렇게 생긴 객체를 선언 및 초기화할 때 생기는 일에 대해 알아보자.

  1. 먼저 변수 영역의 빈 공간(@1002)을 확보하고 주소의 이름을 obj1로 지정한다.
  2. 임의의 데이터 저장 공간(@5001)에 데이터를 저장하려니 여러 프로퍼티로 이루어진 데이터 그룹이므로, 그룹 내부 프로퍼티들을 저장하기 위한 별도의 변수 영역을 마련하고 그 영역의 주소(@7103~)를 @5001에 저장한다.
  3. @7103과 @7104에 각각 a, b라는 프로퍼티 이름을 지정한다.
  4. 데이터 영역에서 1을 검색하고, 없으므로 임의로 @5003에 저장한 뒤 이 주소를 a가 가리키도록 @7103에 저장한다. "bbb"도 이와 같은 과정을 거친다.

위로부터 알 수 있듯 데이터 영역에 저장된 값들은 모두 불변값이지만, 객체가 별도로 할애한 영역은 "변수 영역"이고 여기에는 얼마든지 다른 값을 대입할 수 있다.

이 때문에 참조형 데이터는 불변하지 않는 값, 즉 가변값이라고 한다.

✔️ 참조 타입의 값 복사하기

참조 타입의 변수들은 데이터 복사가 일어날 때 값이 담긴 주솟값을 바로 복사하지 않고, 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복사한다.

var obj1 = {
  a: 1,
  b: "bbb"
};
var obj2 = obj1;

obj2.a = 20;

console.log(obj1.a); // 20

위의 코드에서, obj2는 obj1이 가리키는 데이터 묶음의 주소를 복사한다. (같은 객체를 보고 있음)
그러므로 obj2에서 프로퍼티의 값을 변경하면, 같은 객체의 주소를 가지고 있는 obj1에서도 값이 변하게 되는 것이다.

하지만,

var obj1 = {
  a: 1,
  b: "bbb"
};
var obj2 = obj1;

obj2 = {
  a: 20,
  b: "cc"
};

console.log(obj1.a); // 1

이처럼 복사 후 obj2에 새로운 객체를 할당해 주게 되면 메모리 데이터 영역의 새 공간에 새로운 객체가 저장되고 그 주소를 변수 영역의 obj2에 저장하게 된다!
즉 obj1과 obj2가 다른 객체를 가리키게 되므로 obj1이 가리키는 값은 달라지지 않는다.

이로부터 알 수 있는 점은, 참조형 데이터를 가변값이라 할 때의 "가변"은 참조형 데이터 자체를 변경할 때(두 번째 경우)가 아니라 그 내부의 프로퍼티를 변경할 때(첫 번째 경우)에만 성립한다는 것이다.


참고자료

코어 자바스크립트(위키북스, 정재남)
[Java Script] 원시타입과 참조타입 👀

profile
응애 나 애기 개발자
post-custom-banner

0개의 댓글