티스토리 뷰

안녕하세요. 좋아요요정입니다!

지난 스터디에서 자바스크립트의 자료형은 크게 원시 타입과 참조 타입으로 구분되고, 참조 타입의 객체에 관해 자세하게 알아보았습니다. 이번에는 원시 타입과 객체 타입의 차이점과 메모리에 어떻게 저장이 되어지는지 구체적으로 살펴보겠습니다. 그리고 객체가 메모리에 저장되는 특징으로 인한 객체의 얕은 복제, 깊은 복제에 대해 이해해보는 시간을 갖겠습니다.

 

 

 


원시타입과 객체타입의 가장 큰 차이점을 말하자면 변경이 가능한지에 대한 여부입니다.

원시 타입은 변경이 불가능한 값, Immutable type이고, 객체 타입은 변경이 가능한 가변성을 가진 mutable type입니다.

 

 

 

원시 값은 메모리에 어떻게 저장될까요?

먼저 원시 값이 메모리에 어떻게 저장되는 지 살펴보겠습니다.

let name = 'cookie';
let color = '삼색이';
let age = 2;

 

프로그램이 실행될 때 메모리의 영역이 네가지 영역(코드 영역, 데이터 영역, 힙 영역, 스택 영역)으로 구분되어 데이터를 저장하고 처리하는데 이때 원시 값들도 함께 불려와져 메모리상에 존재하게 됩니다. 원시 값의 경우 String, Number, Bigint, Boolean, Undefined, Symbol, 그리고 Null 값으로 메모리 공간을 얼마나 사용할 지 사전에 정의가 가능합니다.

자바스크립트가 실행이 되면서 메모리의 코드 영역에 코드가 저장되어 코드를 해석하고, 우선 메모리 공간을 찾아 선언한 변수의 이름을 붙이고 우리가 임의로 수정이 불가능합니다. 개발자가 원시값을 변수에 할당하면, 변수에는 실제 값이 복사되어 저장됩니다. 

 

자바스크립트의 모든 선언은 코드영역에서 해석하고, 변수명을 메모리에 먼저 할당, 이후 코드가 실행되며 값이 등록되며 호이스팅이 일어납니다. 호이스팅은 Hoisting, 끌어 올리다는 뜻으로 선언문 이전에 이미 변수명이 선언되어 있는 상태로 선언된 코드블럭 이전에 이미 선언되어 호출이 되는 것을 뜻합니다. 

console.log(cat); // undefined
var cat;

console.log(cat2); // Error: Uncaught ReferenceError: bar is not defined
let cat2;

var의 경우는 undefined의 값을 대입한 후 이후 실행 단계에서 개발자가 할당한 원시 값을 메모리 영역에 저장이 됩니다.

ES6에 추가된 let, const의 경우 블록 시작부터 선언이 이루어진 라인까지 일시적으로 접근을 막아 호출이 되면 에러를 발생시킵니다. 

var와 let,const 변수에 관한 부분은 차후에 자세히 다루도록 하겠습니다.

 

 

 

다시 돌아와 변수에 다른 값을 대입하거나, 다른 변수명에 값을 복사하면 어떻게 될까요?

 

이미 선언되어있는 변수에 새로운 원시 값을 할당하는 경우 자바스크립트는 새로운 메모리 공간에 새로 할당되는 값을 복사해 입력하고, 기존에 사용하던 변수명이 이를 가리키게 합니다.

 

새로운 변수명에 기존에 있던 변수를 할당하는 경우에는 새로운 변수명이 새로운 메모리 공간에 할당되고, 그 위치에 기존 변수에 할당되어 있던 값을 그대로 복제합니다. 원시 값의 불변성은 저장되어있는 ‘cookie’ —> ‘cookit’ 처럼 부분적인 변경이나, 메모리에 저장되어있는 값을 수정하는게 불가능하기 때문에 불변성을 가지고 있다고 합니다. 이처럼 값을 수정하는, 재할당하는 경우 동일한 메모리주소에 저장되어있는 값을 재할당하는 것이 아닌, 다른 메모리 영역에 저장하고 그 위치를 가리키게 하고 이전 값, 이후 값 모두 메모리상에 존재하게 됩니다.

더 이상 사용되지 않는 메모리 공간은 가비지 컬렉터에 의해 제거되게 됩니다.

 

 

원시값은 스택 영역에 값 자체를 보관합니다.

let cat = 'cookie';
let cat2 = 'cookie';

cat === cat2; //true

let cat3 = cat;
cat2 === cat3; // true
cat1 === cat3; //true

비교 연산자에서 값 자체를 비교하기 때문에 다른 변수명에 저장되어 있어도, 복제가 된 값이어도 같다고 결과가 나옵니다. 동등 연산자(==, 값이 일치한지 확인), 일치 연산자(===, 값과 자료형 모두 일치하는지 비교) 모두 같다고 출력하게 됩니다.

 

 

 

 

 


참조 타입은 메모리에 어떻게 저장될까요?

참조 값은 객체를 예로 보여드리겠습니다. 객체의 경우, 우리가 직접 명시하고 정해진 사이즈가 없기 때문에 개발자가 선언하는 순간 메모리에 등록되어 관리가 됩니다. 객체는 우리가 작성하는 대로 확장이 가능하고, 또 동적으로 프로퍼티들이 변할 수 있습니다. 자바스크립트 엔진은 이 객체를 관리하기 위해 도대체 얼마만큼의 메모리를 할당해두어야 할지 알 수 없습니다.

그렇기 때문에 자바스크립트는 객체를 원시 값과는 다른 방식으로 관리합니다.

 

자바스크립트는 객체를 생성하게 될 때 힙 메모리에 객체 인스턴스를 생성하고, 이 인스턴스가 존재하는 위치를 스택 메모리에 기록하여 사용합니다. 힙 메모리에 저장되어있는 주소를 스택 영역에 저장해두는거죠.

 

 

 

 

그렇다면 똑같은 내용의 객체를 선언하게 되면 어떻게 될까요?

객체가 생성하게 될 때 힙 영역에 저장하고 > 스택 메모리에 힙 영역에 저장주소를 기록합니다. 같은 내용을 가진 객체이지만 다른 주소를 가지고, 다른 영역에 저장되게 됩니다.

이 경우 일치연산자로 cat == cat2를 하면 어떻게 출력될까요? 정답은 false입니다. 참조 타입( reference type)의 비교는 힙 영역에 저장된 메모리 주소를 비교하기 때문입니다. 객체는 똑같은 값이지만, 실제 자바스크립트가 인식하기에는 완전히 다른 힙 영역의 주소를 가리키는 값으로 보게되는 겁니다.

 

 

 

 

그렇다면 객체를 복제하는 경우는 어떻게 될까요? 

새로운 변수에 기존 객체를 할당하는 경우 힙 영역의 위치를 가리키는 주소를 복제하게 됩니다.

변수명은 다르지만 힙 영역에 동일한 객체를 가리키게 되죠. 일치연산자로 cat == cat2를 하면 true로 출력됩니다. === 의 경우에도 true로 출력합니다.

 

자바스크립트가 참조타입의 데이터를 메모리에 저장하는 이러한 특징 때문에 주의를 해야합니다.

위의 경우 cat과 cat2가 하나의 객체를 가리키고 있기 때문에 cat을 수정할 경우 cat2에도 수정된 데이터가 출력되기 때문입니다. 이유는 같은 주소를 가리키며 동일한 객체를 공유하고 있기 때문입니다.

이처럼 객체가 저장된 주소를 복제하는 것을 얕은 복제, Shallow Copy라고 합니다.

 

 

주소복제가 아닌, 다른 메모리에 객체를 똑같이 복제하고 싶다면 깊은 복제, Deep Copy를 해야 합니다. 변수명을 복제하지 않고, 객체에 속한 모든 내용을 복제할 수 있습니다. 이 때 객체 프로퍼티에 참조값이 저장되어 있는 부분을 주의해 복제를 진행해야 합니다.

객체의 프로퍼티의 값에는 자바스크립트에서 사용할 수 있는 모든 값이 사용 가능합니다. 원시형인 경우 그대로 복제를 진행하면 됩니다. 값이 원시형이 아닌 경우에는 레퍼런스 주소 내부의 값을 복제해 진행할 수 있습니다.

이전에 작성한 게시글을 예시로 링크 걸어두겠습니다. ([react] object 깊은 복사하는 함수)

 

 

 

 


퍼즐이 맞춰지는 기분이 듭니다. 객체의 주소값 저장으로 인한 얕은 복제, 깊은 복제에 대한 이해가 있었지만 메모리에 어떤 방식으로 저장이 되고 있는지 눈으로 보고 끝내는게 아닌 그걸 설명하기 위해 작성하고 다시 되돌아가 찾다보니 연관되어 있던 지식들이 연결되어짐을 느꼈습니다. 자바스크립트가 코드를 불러오고, 저장함으로 인해 일어나는 액션을 액션 한 단위 그 자체로 이해가 하고 있다가 원론적인 부분을 공부하고 보니 왜 그러한 액션이 이루어진 것인지 더 깊이있게 배울 수 있었습니다.

이번주 블로그 작성 목표가 3회 블로그 작성이었는데, 러버덕 스터디를 진행하며 시간가는줄 모르고 블로그 글 작성을 할 수 있었습니다. :) 

2021년 마지막 한주도 뜻깊은 일주일이 되시길 바랍니다.

즐거운 코딩라이프되세요! 감사합니다.

 

JavaScript 스터디 팀 러버덕과 함께 합니다.

 
 
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함