본문 바로가기
Front-End/자바스크립트 (JavaScript)

[자바스크립트] 원시(Primitive) 자료형과 참조(Reference) 자료형

by MS_developer 2022. 9. 13.

배열과 객체 포스팅에서 객체에 대해 정의할 때 "원시 자료형을 제외한 자바스크립트 대부분의 것들"이라는 언급을 했다. 그렇다면 원시 자료형에는 어떤 것들이 있을까? 또 원시 자료형이 아닌 것들은 무엇이라고 부를까? 한 번 알아보도록 하자.


원시 자료형(Primitive data type)과 참조 자료형(Reference data type)

 

진짜 자바스크립트 세계관 최강자들의 싸움이다...

먼저 자료형은 크게 두 가지 종류로 분류가 된다. 

 

1. 원시 자료형 Primitive Data Type

우리가 배웠던 대표적인 원시형 자료들

처음 변수의 선언과 할당에서 배웠던 대부분의 자료형들이 원시 자료형에 포함된다. number, string, undefined, boolean 이외에도 null, symbol(익명의 객체 속성을 만들 수 있는 데이터 형식), bigInt(number로 표현하기에 너무 큰 수를 위한 데이터 자료형)가 원시 자료형에 포함되어 총 7종류로 분류된다. symbol과 bigint의 경우 배우지 않은 생소한 대상이니 존재만 알고 넘어가도록 하자.

이 외의 number, string, boolean, undefined의 경우 typeof 연산자를 활용하면 데이터 타입의 확인이 가능하다. 그런데, 여기서 한 가지 문제점이 발생한다. 

왜 원시 자료형인 null의 type 연산자 값이 object일까? MDN에 따르면 최초에 자바스크립트가 구현 되었을 때 "타입 태그"라는 것이 존재했는데, 객체object의 타입 태그가 0임과 동시에 null의 타입 태그 또한 0으로 설정되어 있었기 때문이다. 이에 따라 typeof 연산자는 데이터 자료형에 따른 타입 태그를 읽어 해당 자료형을 정의하기 때문에 이러한 값이 출력되는 것이다. 이에 따라 "ECMAScript에 수정이 제안되었으나 거절"되었다고 한다. (거절 사유는 '기존에 존재하는 많은 웹사이트들에 오류를 유발'하기 때문이라고 한다.)

원시 자료형의 대표적인 특징을 고르자면 원시 자료형은 "불변하여 변형할 수 없다"는 점이다. 변수를 통해 할당된 값이 만약 원시 자료형에 해당할 경우, 해당 값은 "재할당"은 가능하지만 "변형"은 불가하다. (4를 5로 바꿀 수는 없지만 4가 저장된 변수 a에 5를 재할당 할 수는 있다는 소리다.) 

또한 원시 자료형은 '하나'의 자료형을 담고 있기 때문에 여러 개의 자료를 동시에 담을 수 없다. 위처럼 함수 안에 전달된 값은 변하지 참조 자료형이 아니기 때문에 초기에 할당된 값을 유지한다. (단, 함수를 실행시킬 경우 값이 재할당 되는데, 이 부분의 경우 스코프 포스팅에서 더 자세한 설명을 볼 수 있다.)

 

2. 참조 자료형 Reference Data Type

대표적인 참조 자료형들을 typeof 연산자를 활용해 확인해 보았다

MDN은 원시 자료형에 대해 "객체가 아니면서 메서드도 가지지 않은 데이터"라고 정의하는 한편, 자바스크립트 언어의 타입을 원시 자료형과 객체(참조 자료형)으로 나누었다. 자바스크립트 참조 자료형은 Array(배열), Object(객체), Funciton(함수)로 나뉘는데, 배열과 객체 포스팅에서 언급했듯 배열과 함수는 결국 객체의 일부다. 이에 따라 참조 자료형은 "자바스크립트 안에 한해서는" 객체를 가리킨다고 봐도 무방하다.

그런데 이게 왠걸? typeof 연산자를 활용해보니 함수는 'function'이라는 개별적인 타입을 가지고 있는 것으로 보인다. 왜 'object'가 아닐까? 이에 대한 해답으로 ECMAScript2015는 "함수 프로토타입 객체는 2015년 이전에 생성된 ECMAScript 코드와의 호환성을 위해 typeof 연산자에 대해 '함수'라는 별도의 결과값을 반환한다"고 밝혔다. 즉, 함수는 여전히 객체의 일부가 맞지만 자바스크립트가 ECMA의 표준을 따르고 있기 때문에 지정된 문법적 예외라고 보면 될 것 같다.


Stack과  Heap Memory

원시 자료형과 참조 자료형에는 또 한 가지 큰 차이점이 존재하는데, 바로 메모리 저장 방식이다. 

STACK

let a = 5; let b = 2; let str = 'string'; let greetings = 'hello';
let isTrue = true; let isFalse = false; let null = null; let arr = [];
heap에 arr이라는 주소 생성
HEAP

arr = [2,3,4]

1. 스택Stack (원시 자료형 저장)

변수를 선언하고 원시 자료형을 할당하면 이를 스택stack이라는 메모리 공간에 저장한다. 이 후에도 계속해서 여러 개의 변수가 선언되고 원시 자료형이 할당될 때 마다 스택에 계속해서 값이 저장되는데, 각각의 값이 할당된 메모리 공간은 간섭할 수 없다. 이 때문에 원시 자료형은 "불변하며 변할 수 없다"는 설명이 가능한 것이다. 쉽게 생각해서 개개인이 사물함을 가지고 있고, 이 공간은 해당 개인(변수)만 접근할 수 있다고 생각하면 된다.

 

2. 힙Heap (참조 자료형 저장)

힙은 가상의 메모리 공간으로 참조 자료형의 데이터를 저장하는 공간이다. 참조 자료형은 빈 공간에 자료가 주어짐에 따라 그 크기가 늘어나고 지움에 따라 그 크기가 줄어드는 장점이 있는데, 이는 힙이라는 데이터 저장 공간에서 비롯된 특성이다. 힙은 스택과 달리 정해진 저장공간이 없고, 하나의 큰 데이터 보관함 안에 여러 개의 '주소'들과 이에 따른 '자료'들을 보관한다. 만약 거대한 공터에 책(데이터)들이 쌓여있다면, 우리는 책이 "어디"에 쌓여 있는지 (또는 책의 제목이) 적혀 있는 쪽지를 이전의 스택(사물함)에 놓는다. 이를 통해 우리는 거대한 공용 공간에 '원하는 만큼'의 자료를 저장할 수 있게 된다.


참조

 

ECMAScript 2015 Language Specification – ECMA-262 6th Edition

5.1.1 Context-Free Grammars A context-free grammar consists of a number of productions. Each production has an abstract symbol called a nonterminal as its left-hand side, and a sequence of zero or more nonterminal and terminal symbols as its right-hand sid

262.ecma-international.org

 

댓글