Pie_Archive

[Java Script] 11. 원시 값과 객체의 비교 본문

Study/Java Script

[Java Script] 11. 원시 값과 객체의 비교

코딩파이 2022. 8. 3. 23:23

** 본 글은 모던 자바스크립트 DEEP DIVE 를 읽고 정리한 글입니다.
** 본인이 책 내용의 이해를 돕기 위해 정리한 글이며, 부정확한 정보전달이 있을 수 있습니다. 
** 피드백은 언제나 환영입니다!


 

데이터 타입을 배울때 6개의 원시타입객체타입 까지 총 7개의 타입을 학습했다.

근데 왜 객체만 따로 타입을 나누는 걸까?

간단하게 차이점을 설명 후, 자세히 알아보자.

 

0. 원시 값과 객체 값의 차이, 3 가지

1. 원시 값변경이 불가능한 값
객체 값변경이 가능한 값

 

2. 원시 값은 변수에 할당 시 메모리 공간에 실제 값이 할당된다.

원시 값 할당 과정

 

객체 값 객체 값이 저장된 메모리 주소를 변수 메모리에 할당한다.

객체 값 할당 과정


 3. 값이 할당된 변수를 다른 변수에 할당하면,
원시 값값 자체가 복사되어 전달되는 반면

원시 값 변수 복사의 과정

 

객체 값 메모리 주소를 복사하여 전달한다.

객체 값 변수 복사의 과정

 

위 그림과 축약된 설명으로는 이해가 어려울 수 있으니,

아래서 자세히 알아보자!

 

1. 원시 값

1. 변경이 불가능한 값

메모리에 저장 된 값들은 변경이 불가능하다.

"어? 변수에 원시 값인 문자열을 할당해도 재 할당이 가능한데...?"

라고 생각 했다면, 변수 부분을 다시 읽어보길 권장드린다.

변수는 재할당 될 때 메모리에 할당되어 있는 값이 직접적으로 변하는게 아니라,

다른 메모리에 재 할당할 값을 생성 후, 그 생성된 메모리의 주소를 변수에 다시 참조시키는 것이다.

그리고 재 할당 이후 쓰이지 않는 값은 자바스크립트의 가비지콜렉터가 정리를 도와준다.

var a = 'a';
a = 'A';

a 변수를 A로 재 할당할 때, 새 메모리에 값을 생성 후 변수에 메모리 주소를 재참조 시킨다.

 

2. 값에 의한 전달

값이 할당 된 변수를 다른 변수에 할당하면 메모리는 어떻게 동작할까?

참조할 변수의 메모리주소를 따라가 값을 복사한 후,

새로운 메모리에 할당하고 이 새로운 주소를 변수에 참조한다.

같은 값을가진 메모리가 하나 더 생성된다고 보면 된다.

var a = 'a';
var 에이 = a;

에이 = "에이";
console.log(a, 에이); // a, 에이

식별자 a를 새 변수 에이 에 할당하는 과정. 참조한 메모리의 값을 새 메모리에 똑같이 할당 후, 할당한 주소를 참조한다

변수들은 완전히 다른 메모리를 참조하고 있기 때문에, 한쪽 값을 변경해도 다른 값에는 어떠한 영향을 미치지 않는다.

사실 이런 방식의 복사를 당연하다고 생각하고 있다면,

이제 객체를 알아보자.

 

2. 객체

0. 객체는 왜 변경 가능할까?

원시 값들과 달리 왜 객체 값변경이 가능할까?

이유는 객체 값의 생성이 원시 값의 생성에 비해 비용(일)이 많이 들기 때문에

원시 값과 다른 방식으로 설계되어 변경이 가능하다.

 

1. 변경 가능한 값

객체를 변수에 할당하면 무슨 일이 일어날까?

var recipe = {
  분야: "한식",
조리시간: "30분",
 // 이외 아주 복잡하다.
}
recipe.조리시간 = "35분";

제육볶음 레시피를 객체로 가정하여 설명한 객체 생성 및 할당의 과정

원시 값의 경우 변수에 메모리 주소를 담고 → 메모리에서 값을 참조 하는 방식 인데 반해,

객체 값변수에 메모리 주소를 담고 → 이 메모리 주소엔 객체가 저장된 메모리 주소가 담겨있는데 → 객체가 저장된 메모리 주소까지 참조하여 접근한다.

조금 더 쉽게(?) 예시를 들어보자

레시피와 재료로 비교하는 객체와 원시 값

여기서 고춧가루는 원시 값,
객체 값는 제육볶음 레시피 로 비유하여 설명하겠다.

우리가 글을 쓸 때, 고춧가루제육볶음 레시피 에 대해 설명이 필요하다고 하자.
그럼 고춧가루의 설명에 대해 "고춧가루는 고추를 말려서 빻은 가루" 라고 쉽게 작성할 수 있다.

그러나 제육볶음 레시피를 적는다면
들어가는 재료와 순서, 유의사항 등 적을 것들이 아주 많아진다.
이걸 매 번 직접 적고 있다면 아주 번거롭고 힘들지 않을까?

때문에 우리는 앞으로 제육볶음 레시피를 따로 적어놓고
제육볶음 레시피를 쓸 때 마다 해당 링크를 첨부하기로 했다.

이렇게 쉬운 원시 값들은 바로 값을 참조하는 반면
복잡한 객체 값들은 외부 링크를 참조하는 형식으로 이해한다면
자바스크립트에서 왜 객체를 이러한 참조 방식 으로 처리하는지 좀 더 이해할 수 있다.
제발 이해가 되었으면 좋겠다.

자 그럼 이런식으로 쓰는 것을 최소화 하기 위해 외부 링크까지 처리했는데

매번 수정사항이 생길 때 마다 레시피를 처음부터 끝까지 다시 작성하여 수정하고 있다면 얼마나 비효율적일까?

그렇기 때문에 객체는 값 자체(레시피 자체) 를 변경 할 수 있도록 한 것이다.

그러나 이런 구조의 단점이 있는데,

여러 개의 식별자가 하나의 객체를 공유한다는 점이다.

 

2. 참조에 의한 전달

어렵게 이해하지 말자.

여러개의 식별자가 하나의 객체를 공유한다는 것은

내가 제육볶음 레시피의 링크를 첨부할 수도 있고

내 친구나 동료가 내가 작성한 제육볶음 레시피를 첨부할 수 있다는 점이다.

그럼 우리는 모두 같은 제육볶음 레시피(객체 값) 를 공유하고 있는 것이다.

 

그럼 나, 혹은 동료가 이 레시피를 수정한다면 어떻게 될까?

당연히 이 레시피를 참조한 사람들의 글 모두 수정되는 셈이다.

var recipe = {
 분야: "한식",
 조리시간: "30분",
 // 이외 아주 복잡하다.
}

var teamRecipe = recipe; // 우리 팀에서 내 제육볶음 레시피를 참조하였다.
teamRecipe.조리시간 = "25분"; // teamRecipe 에서 조리시간을 수정하였다.
console.log(recipe, teamRecipe); // 둘 다 수정된다.

우리는 모두 같은 객체 값(레시피)를 공유하고 있기 때문에, 레시피(객체 값)을 수정하면 공유하는 사람들의 레시피 또한 모두 수정된다.


오늘의 후기

객체의 참조와 관련된 부분은 원래부터 중요하다고 생각하여 한번 다시 공부하고 싶었다.

그래서 내가 이해한 부분을 최대한 쉽게 설명하고자 열심히 노력했는데

쓰라는 지식은 없이 웬 제육볶음 레시피만 하루종일 강의 한 느낌이다(...)

깊은복사 / 얕은복사 처럼 온전히 객체를 이해할 때 어려울 만한 부분은 제외하고 작성했는데

나중에 정신 멀쩡할 때(?) 다시 한번 수정을 거쳐야겠다.