프로그래밍/JavaScript

[자바스크립트 개발자가 알아야 할 33가지] #2 원시 자료형

mhko411 2021. 11. 16. 15:55
728x90

자바스크립트의 데이터 타입은 크게 원시 타입과 객체 타입으로 나눌 수 있다. 여기서 숫자, 문자열, 불리언, null, undefined, Symbol은 원시 타입이다. 이번에는 이러한 원시 타입의 특징을 자세히 알아보려고 한다.


원시 타입과 객체 타입의 차이점

원시 타입과 객체 타입의 차이점은 크게 세 가지가 존재한다.

  • 원시 타입의 값은 변경 불가능한 값이고 객체 타입의 값은 변경 가능한 값이다.
  • 변수에 원시 타입의 값을 할당하면 실제 값이 저장되고 객체 타입의 값을 할당하면 참조 값이 저장된다.
  • 원시 타입의 값은 값에 의한 전달, 객체 타입의 값은 참조에 의한 전달이 된다.

여기서 변경 불가능한 값, 실제 값이 저장, 값에 의한 전달은 원시 타입의 특징이라고 할 수 있다. 이 3가지 특징이 무엇을 의미하는 것인지 이해해보자.

 

변경 불가능한 값(Immutable value)

원시 타입의 첫 번째 특징은 변경 불가능한 값이라는 것이다. 처음에 공부를 할 때는 변수에 정수나 문자열을 저장하고 이후에 다른 값을 다시 저장할 수 있는데 왜 변경 불가능한 값이라는 것이지?라는 생각이 들었다. 

 

하지만 변경 불가능하다는 말을 변수의 시선이 아닌 값의 시선에서 봐야한다. 아래의 코드를 보자.

let x = 10;
x = 20;

변수 x에 10을 할당하였다. 이때 10을 저장할 메모리 공간을 확보하고, 확보한 메모리 공간의 식별자를 x로 지정하였다. 그렇다면 x가 가리키는 공간에 10이 저장된다. 이후 변수 x를 20으로 재할당한다면 새로운 메모리 공간을 확보하고, 확보한 메모리 공간에 20을 저장한다.

 

이처럼 값은 이전의 메모리에 그대로 저장되어있고, 새로운 값은 새로운 메모리 공간을 확보한 후에 저장한다. 따라서 원시 타입의 값은 변경 불가능한 값이며 값이 변경되는 것은 새로운 메모리 공간을 확보하고 새로운 값이 저장되는 것이다.

 

만약 원시 값이 변경 가능하다면?

그렇다면 원시 타입의 값은 왜 변경 불가능한지 궁금했다. 이를 위해 원시 값이 변경 가능한 경우로 알아보려고 한다.

위에서 사용했던 코드에서 원시 값인 10을 저장하기 위해 메모리 공간을 확보하고 x라는 이름의 식별자로 지정했다. 이후에 다시 20으로 변경하려고 할 때 현재 10이 저장된 메모리 공간을 20으로 변경하게 된다.

 

만약 위의 경우처럼 기존의 메모리 공간에 저장된 값이 변경된다면 예기치 않은 상황에서 값이 변경될 수도 있다는 것을 의미한다. 그렇다면 상태 변경을 추적하기 어렵게 된다.

 

따라서 원시 값을 변경 불가능하게 하여 데이터의 신뢰성을 확보할 수 있게 된다.

 

값에 의한 전달

아래의 코드를 보자. apple에 10을 저장하고 banana에 apple을 저장하였다.  apple과 banana를 출력하면 10이 출력될 것이다. 이후 apple에 50을 저장하면 apple은 50이 출력되고 banana는 어떤 값이 출력될까?

let apple = 10;
let banana = apple;

console.log("apple", apple); // 10
console.log("banana", banana); // 10

apple = 50;

console.log("apple", apple);
console.log("banana", banana);

원시 타입은 값을 전달한다. 따라서 처음 banana에 apple을 저장했을 때 메모리 공간을 확보하고 banana로 식별한 다음 apple의 주소가 아닌 apple에 저장된 값인 10이 전달되어 저장되었다. 이후 apple에 50을 재할당하더라도 banana와 별개의 동작이 된다. 

 

이를 통해 원시 타입이 값에 의한 전달이라는 것을 확인할 수 있다. 


객체 타입

아래의 코드를 통해 객체 타입을 간단하게 알아보자. 변수 student에는 객체가 실제로 저장된 메모리 공간의 주소가 저장되어 있다. 따라서 원시 타입과 다르게 "변수 student는 값을 갖고있다"라고 말하는 것이 아니라 "변수 student는 객체를 가리키고 있다"라고 표현하는 것이 옳다.

const student = {
  name: "alex",
  age: 16,
};

 

객체는 왜 변경 가능할까?

원시 값을 갖는 변수는 재할당을 통해 저장된 값을 변경하지만 객체의 프로퍼티는 재할당 없이 저장된 값을 변경하고, 새로운 프로퍼티를 추가 및 삭제를 할 수 있다. 이처럼 객체는 왜 변경 가능하도록 되어있을까?

 

객체에 동적으로 프로퍼티를 추가할 수 있다. 이때 객체의 크기가 매우 커질 수도 있다. 따라서 재할당이 이루어지려면 기존의 객체의 크기만큼 새로운 메모리 공간을 확보해야 하는데 생성 비용이 많이 든다. 즉, 메모리를 효율적으로 사용할 수 없다. 그렇기 때문에 객체는 재할당없이 값을 수정할 수 있도록 되어있다.

 

참조에 의한 전달

객체 타입을 저장한 변수는 실제 객체가 생성된 메모리 공간의 주소를 참조하고 있다. 아래의 코드를 보자. 

student2에 student1을 할당하면 객체의 주소를 할당하게 되는 것이다. 이때 student1의 name을 변경하면 student2에도 영향이가게 된다.

const student1 = {
  name: "alex",
  age: 16,
};

const student2 = student1;

student1.name = "park";

console.log(student1);
console.log(student2);

위의 코드처럼 두 개 이상의 식별자가 하나의 객체를 공유하는 문제가 있다.