본문 바로가기
FE/Javascript

Primitive type & Reference type

by ideal_string 2022. 9. 20.

Primitive type(원시타입)과 Reference type(참조타입)은 프로그래밍의 근간이다. 이에 대한 이해도가 없다면 for문을 배워도 if를 배워도 금방 한계에 봉착한다. 어려운 것은 아니나, 그렇다고 빠르게 이해할 수 없었떤 두 가지를 정리한다. 간단 비교하고 시작하자면 원시타입은 정수, 실수, 불린 등 실제 데이터를 담은 것이고, 참조타입은 해당 데이터가 담긴 주소를 갖고 있다.

Primitive type

원시타입은 객체나 메서드가 아닌 데이터 그 자체를 갖고 있는 것을 말한다. 대부분의 저급 언어가 가진 특징이며, 이미 생성한 원시타입의 값은 불변하다는 특징을 갖는다. 자바스크립트에서 원시타입은 7개만 알면 끝이다(ES6 기준). 원시타입의 종류와 기본 특징은 아래와 같다.

string 문자열
number 실수, 정수 등을 모두 포함한 숫자(-(2^53 − 1)부터 2^53 − 1까지의 수). +Infinity, -Infinity, NaN 값도 포함.
bigint Number보다 더 큰 2^53-1 보다 큰 정수를 포함
boolean true(참)과 false(거짓)으로 이뤄진 논리 데이터
undefined 값을 할당하지 않은 상태
symbol 유일하고 변경 불가능한 타입
null 존재하지 않거나 유효하지 않은 상태(빈 상태)

string이나 number등 한 번에 이해할 수 있는 타입이 있는 반면, undefined와 null, 그리고 symbol 같이 무슨 말인가 싶은 타입이 있다. 한 번에 서술하기엔 조금 길어질 수 있어 따로 정리했다. undefined와 null은 지난 번 이미 게재했고, 근시일 내에 symbol도 따로 정리할 예정이다. (이 글에는 전체적인 특징만 서술한다.)

불변?!

원시타입의 특징 중 하나인 불변한다는 점이 처음에 쉽게 와닿지 않는다. let을 쓰면 언제든 재할당이 가능하다는 의문이 바로 들기 때문이다. 이때 재할당 여부의 문제가 아니라 컴퓨터에서 동작하는 방식이다.

let bar = "abc";
console.log(bar);        // abc
bar.toUpperCase();
console.log(bar);        // abc

bar라는 변수에 abc 문자열을 넣은 후 출력했을 때와 bar라는 변수를 대문자료 변환시키는 toUpperCase()를 실행하고 다시 출력했을 때 모습이다. 결과값이 전혀 바뀌지 않은 것을 볼 수 있다. 원시타입의 경우 해당 값을 가지고 아무리 많은 변경을 주어도 해당 값은 변하지 않는다. 이게 불변하다는 점이다. 

bar = bar.toUpperCase(); // ABC

위와 같이 코드를 쓰면 되는거 아니냐고 반문할 수 있다. 이는 원시 값에 새로운 값을 부여한 것으로 기존 값을 직접 변형한게 아니다. 이는 메모리에 저장된 상태를 보면 이해할 수 있다. 예를 들어 변수 bar은 Ox123이라는 주소를 할당받고 "abc"라는 값을 넣어둔 상태다. Ox123이라는 주소에 할당된 "abc"는 절대 변하지 않는다. 여기서 같은 변수에 재할당한다면? bar은  Ox124라는 주소를 다시 부여 받은 후 "ABC"라는 값을 넣는다. 이때 Ox123은 메모리에 그대로 남아있기에 원시타입은 불변하다고 말한다.

 

Reference type

참조 타입은 한문장으로 '원시 타입을 뺀 모든 것'이다. object(객체), array(배열)이 대표다.

object { 키 : 값, 키 : 값 } 키와 값이 한쌍으로 이루어진 조합 뭉탱이
array [ 값, 값, 값, 값 ] 값으로만 이루어진 뭉탱이
set 유일한 값만 존재하는 값 콜렉션 객체
map 키-값 쌍을 보유하고 키의 원래 삽입 순서를 기억하는 객체

원시 타입이 불변하다면 반대로 참조 타입은 언제든 바뀔 수 있느게 특징이다. 물론 이는 원시 타입과 같이 동작 방식에서 차이다.

const abc = [1,2,3,4,5]
console.log(abc) // [1,2,3,4,5]

위와 같이 선언했을 경우 abc가 Ox1111라는 주소를 할당 받고 여기에는 Ox2000이라는 값이 들어 있다. 이 값은 배열의 값이 아닌 배열이 담긴 값인 셈이다. Ox2000에 [1,2,3,4,5]가 들어 있다. 다시 정리해보다 abc 변수 주소는 Ox1111, 이 주소 담긴 값은 Ox2000이다. 참조 타입은 원시 타입과 다르게 값을 바로 가지지 않고 주소를 가지고 있다는게 다른 점이다. 이 특징으로 인해 const로 선언 했음에도 배열 내 값을 얼마든지, 바꿀 수 있고 문제도 없다. 다만, const가 상수인 만큼 배열로 설정했을 경우 배열을 객체로 바꾼다는 등의 다른 타입으로 바꾸는 건 불가능하다.

 

마무리

원시 타입과 참조 타입에 대한 이해를 처음엔 알고리즘 문제를 풀면서 필요하다 생각했고, 이후 웹페이지 중 게시판이나 댓글 리스트를 map으로 반복하게 하면서 조건값을 설정할 때 필요성을 느꼈다. 원시 타입과 참조 타입의 이해가 없이도 코딩하는데 무리가 없을 수 있다. 다만, 너무 없다면 리팩토링, 즉 최적화하는 데에 불편함 혹은 당혹감을 느끼기 쉽상이다. 알고나서 취사선택하는 것과 모르고 누가 짠 코드를 따라 최적화하는 건 장기적으로 한계를 느낄 수 있으니 미리미리 알아두는 게 좋은 부분이라 여긴다.

 

※ 잘못된 내용이 있을 경우 댓글로 알려주세요. 배우고 익히고 수정하겠습니다:)

'FE > Javascript' 카테고리의 다른 글

Shallow Copy & Deep Copy  (0) 2022.09.24
== & ===  (1) 2022.09.23
null & undefined  (0) 2022.09.15
let, const, var  (1) 2022.09.14
Destructuring Assignment  (0) 2022.09.13