Web Front-end/JavaScript

[JS/Basic/자료형] 자바스크립트 원시타입,참조타입

JavaScript에서는 자료형을 "메모리에 저장하는 방식"에 따라서, 원시타입과 참조타입으로 나눌 수 있습니다.

(네? 뜬금없이 무슨 메모리 이야기냐구요?  컴공이면 당연히 알아야하는거 아닌가요?)

 

사실, 저희가 짜는 Code의 모든 변수와 로직들은 폰노이만 컴퓨터 구조에서는 메모리에 저장되어집니다. (그게 캐시 메모리일 수도, RAM 일수도, 심지어 가상메모리 공간일 수도 있습니다.) 메모리 관리기법, 컴파일러의 역할, JS 엔진의 역할 등을 말하면 이 글은 천페이지를 넘길 수 있기 때문에 복잡한 이야기는 각설하고 하나만 기억하면 됩니다!

"JS에서는 원시타입과 참조타입이 있다."

  • 원시타입문자열, 숫자,참/거짓, undefined,Symbol,null이 있습니다. 그 외에는 다 참조값입니다.
  • 참조타입은 대표적으로 함수,객체, 배열 등이 있을 수 있습니다.

자바스크립트 원시타입(primitive)

  • 문자열 , 숫자형 , Boolean,  Undefined , Symbol, null이 있습니다.
  • "불변성"을 가집니다.
  let name ="mapin"; //문자열
  let age= 24; //숫자형 
  let isGood= true;//Boolean

위와 같은 코드가 있을 때, 원시값인 경우는 아래와 같이 동작하게 됩니다. 저장된 값을 변수가 직접적으로 가리키는 형태를 띄게 됩니다. 

도식화

먼저, 원시값의 불변성에 대해서 부터 짚고 넘어가겠습니다. 아래의 코드를 보시죠.

let num1 = 100;
num1 = 500;

console.log(num1);

혹시, 위의 과정이 이렇게 흘러간다고 생각하시지 않았나요? num1에 저장되어있는 100을 500으로 바꾼다.

위 그림은 틀렸습니다. 자바스크립트에서는, 대부분의 언어에서는 위와같이 "수정"하는 비효율적인 짓은 하지 않습니다. 

500의 값을 가지는 메모리 공간을 새로 만들어, num1과 연결시켜주면 되거든요. 즉, num1의 값은 한 번 할당된다면 변하는게 아니고 재할당이 될 뿐입니다. num1을 직접적으로 수정할 수는 없습니다. 이러한 관점에서 "불변성"이라고 합니다.

왜 "수정"이 더 비효율적인지는 자세하게 다루지 않겠습니다. 나중에 OS 글을 업로드하게 되면 꼭 적어놓겠습니다.

이러한 과정으로 원시값은 할당이 됩니다. 이제, 원시값이 "복사(Copy)"가 일어난다면 어떻게 될까요? 아래의 코드를 봅시다.

let num1 = 100;
let num2 = num1;
///
num1 = 5000;

아래의 그림이 이제는 이해가 가실겁니다. 원시값의 복사는 value를 그대로 복사해서, 다른 메모리 공간에 "할당"할 뿐입니다. 이 현상을 제일 잘 볼 수있는 곳은 "함수의 매개변수" 입니다. 또 코드를 하나 보시죠!

let num1=5
let num2=8

function adder(num1,num2){
	num2= num1+num2;
    	return num2
} 


let res = adder(num1,num2)

//what is num2??
//What is res??

num2와 res의 값은 뭘까요 ? num2는 num1+num2를 했으니까 13일까요? res는 13일까요?

  • num2는 그대로 8이고 , res는 13입니다. Parameter의 타입이 원시타입이므로 복사가 일어날 때, 값 자체가 복사가 됩니다. 따라서, 원본의 num1,num2는 변하지 않죠. 이러한 현상을  "Call by Value"라고 하기도 합니다.

자바스크립트 참조타입

  • 참조타입은 원시형이 아니면 참조타입 입니다. 대표적으로 함수,객체, 배열 등이 있습니다.
  • 참조타입은 원시타입과 다르게, 해당 값의 "주소값"을 가지고 있습니다. 
const arr = [1,2,3,4,5] 

const func1 = (a,b) => a+b;

이제, 아래의 그림에 대해서는 설명을 안해도 되겠죠? 메모리 공간에 다음과 같이 할당이 됩니다. (정확히는 arr도 메모리 안에 있지만, 가독성을 위해서 밖으로 뺏습니다) 

참조타입은 복사가 되면 , "주소값"이 복사되겠죠? 그러면, 어떻게 될까요? 같은 곳을 가리키는 2개의 변수가 만들어지게 됩니다. 즉, 복사한 값이 원본의 값을 변경하게 되게 됩니다. 아래의 코드를 보시죠.

const arr1=[1,2,3,4,5];

const arr2 = arr1;

arr2[0]=5;
arr2[1]=4;

console.log(arr1)
// [1,2,3,4,5] ??
// [5,4,3,4,5] ??

[5,4,3,4,5]가 출력되는 것을 볼 수 있을겁니다. 따라서, 의도치않게 원본의 값을 변경하는 경우가 생기게 됩니다.

위의 원시값의 예시처럼, 함수의 Parameter로 객체나 함수가 들어갈 때, 원본의 값을 변경하지 않고 싶은데, 원본의 값이 변경되는 경우가 있겠죠 ? 로그인 과정인데, 암호화를 하는 과정에서 고객의 아이디를 "진짜" 암호화 시키면 안되잖아요!?

 

따라서, 이 차이점을 이해하는 것은 중요합니다!  오늘은 글이 길었군요! 빠이! 

 

 

Refer) 참고 블로그 , 사이트

제로초님의 블로그

nomadhash님의 Velog

모던 자바스크립트 튜토리얼 객체의 복사

MDN 원시값