프론트엔드 개발/JavaScript

자바스크립트) 원시타입 VS 참조타입 / 얕은복사 VS 깊은 복사

Ella Seon 2023. 2. 3. 14:12

1. 데이터타입(값의 종류)

- 자바스크립트의 모든 값은 데이터 타입을 가짐

- ES6 는 7개의 데이터 타입을 제공함

구분 데이터 타입
원시형 1) 숫자 
2) 문자열
3) 불리언
4) undefined 
5) null               
6) 심벌
참조형 1) Array
2) Function
3) Date
4) Map,WeakMap
5) RegExp
6) Set,WeakSet

 

1-1) 원시형 VS 참조형의 차이

원시형 참조형
원시 값이 변경 불가능하다. 

불변성 : 한번 만든 원시값을 바꿀수 없는 것이 불변성이다. 즉 변수의 값을 변경하려면 재할당만 가능하다. (원시값을 바꿀 수 없으니)
할당된 메모리 공간에 이미 존재하는 원시값을 변경할 수 없음을 의미한다. 다시 말해, 변수에 새로운 원시값을 할당하려면 기존의 메모리 공간을 바꾸는 것이 아니라, 새로운 메모리 공간에 새로운 원시값을 할당해야 합니다.

참조형 데이터 자체가 아닌 내부 프로퍼티의 데이터를 변경할 때 변경가능하다. 

가변성 : 참조형 데이터 자체를 변경(새로운 데이터를 할당하는것) 할 경우는 불변값이고 그 내부의 프로퍼티를 변경할 때만 가변성이 성립된다. 객체를 할당한 변수는 재할당 없이 객체를 직접 변경할 수 있다. 객체 데이터 자체를 재할당 없이 내부 프로퍼티를 변경,추가가 가능하다. 

이런 가변성은 다양한 상황에서 유용하지만, 예기치 않은 부작용(side effects)을 일으킬 수도 있다. 이러한 이유로, 함수형 프로그래밍에서는 불변성(immutability)을 선호하고, 객체나 배열을 변경하는 대신 새로운 객체나 배열을 생성하는 방식을 많이 사용한다.

에 의한 전달
(원시값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달된다.) 

변수에 변수를 할당할 때 (let a = 10, let b = a) 원시값 자체가 복사된다. 10이라는 원시값 자체가 복사된다. 따라서, b에 새로운 값을 재 할당하면 다른 메모리 주소에 할당하기 때문에 변수 a와 b가 독립적으로 다른 값을 갖게 된다.
참조에 의한 전달
(객체를 가리키는 변수를 다른 변수에 할당하면 참조값의 메모리 주소가 복사된다. 참조타입의 변수 b에 내부 프로퍼티를 변경하면 원시타입과는 달리 변수 a도 변경이 같이 된다. 즉, 서로 독립적이지 않고 같은 값을 공유한다. 바로 같은 참조값의 메모리 주소를 바라보고 있기 때문이다.)

 

※ 앞으로 예시 그림에 나오는 메모리 주소는 임의로 보기 편하게 필자가 작성한 것입니다.  실제 메모리 주소는 아닙니다.

 

✅원시형

1) 불변성을 띈다. (메모리 관련 기본 배경지식을 갖고 읽으면 도움이 됩니다~)

💛 불변성이란? 💛

불변성은 사전적 의미로 변하지 않는 성질을 뜻한다. 즉, 한번 만든 원시값을 바꿀수 없는 것이 불변성이다.  엥? 변수의 값을 let이나 var 키워드로 하면 변수의 값을 바꿀수 있는거 아닌가? 라고 생각했을 것이다. 
또, 변하지 않는건 상수 변하는 건 변수 아닌가? 라고 생각했을것이다. '원시값'은 변경 불가능 하다는 말은 원시 값 자체를 변경할 수 없다는 것이지 변수값을 변경할 수 없다는 것은 아니다. 변수는 언제든지 재할당을 통해 변수값을 변경(엄밀히 말하면 교체) 할 수 있다. 

변수와 상수를 구분 짓는 건  변수값이 변경이 안되면 상수, 변경이 되면 변수이다. 뭔말이냐? 

변수는 하나의 값을 저장하기 위해 확보한 메모리 공간을 뜻한다. 변수에 데이터를 할당할때 2군데(변수값 영역 / 원시값 영역) 에 나눠서 메모리 공간을 확보한다. 2군데(변수값 영역/원시값 영역)가 무슨말이지??  
(※ 변수 값 영역, 원시 값 영역은 편의를 위해 지어낸 말이다. )


예를 들어 let a = 'abc' 를 표현하면 아래와 같이 표현할 수 있다. 
(메모리 주소는 구분하기 위해 #을 붙였다. 실제로는 주소값이 이런형태는 아니다. )

아래 그림과 설명을 같이 보자
 
메모리 상의 데이터 할당 순서
1) 변수명 a를 담기위해 메모리의 빈공간인 #1003 에 식별자 a를 지정한다. let a; 라고 최초 변수를 선언할때는 변수 값에 undefined가 할당된다. 
2) let a = 'abc'라고 할당을 하면 #1003 공간에 바로 데이터 'abc'를 저장하는게 아니고 또 새로운 메모리 공간(#1234) 에 원시값(데이터) 'abc'를 저장한다.
3) #1234 주소를 #1003 공간에 대입한다.
( 'abc' 의 값이 만약 #2000 에 담겨있다면 새로운 메모리 공간을 만드는게 아니고 #2000 주소를 가져온다)

4) a = 'bbb'로 재할당하면 어떤 현상이 일어날까?
'abc' 를 담고있는 #1234는 고대로 남겨두고, 새로운 메모리 공간에 'bbb' 라는 데이터를 할당한다.

즉, 기존 문자열을 담고있는 메모리 공간(#1234) 안의 'abc'를 'bbb'로 수정하는게 아니라 무조건 새로운 공간의 메모리를 만들어서 별도의 공간에 저장한다.(만약, 'bbb'값이 기존 메모리 공간에 존재하고 있었다면 새로운 메모리 공간을 또 따로 만들지 않고 원래 있던 'bbb'값의 메모리 공간의 주소를 대입한다.)


요약 : 변수 값을 변경하기 위해 원시값을 재 할당하면 새로운 메모리 공간을 확보하고 재할당한 값을 저장한 후, 변수가 참조하던 메모리 공간의 주소를 변경한다. 원시값은 변경 못하고, 변수값의 메모리 주소만 교체할 수 있는 것이다. 

 

2) 변수에 변수를 할당할 때 원시 타입은 값 자체를 복사한다.

💛변수에 변수를 할당할 때 무엇이 어떻게 전달이 될까? 값에 의한 전달💛
질문) a 에다가 80을 저장하고, b변수에 a를 할당했다.  처음 콘솔창에는 예상했던대로 80 80이 나왔다.
그런데.. b를 100 이라고 변경하고 콘솔창에 a,b를 출력해보면 80 100이 나온다..왜그럴까?
b가 a라고 했으니 b를 100이라고 변경했으면 a도 100으로 변해야되는거 아닌지..? 라는 생각이 들었을것이다. 

1) let a = 80; 이라고 변수 a 에 값을 할당했다.  빈 메모리 공간에 메모리 주소 #3000를 확보하고 #1003 주소에 원시값 80을 저장한다.  그리고 변수값에는 #1003 주소를 참조한다. 
2) let b = a ; 이제 복사를 할 차례! 빈 메모리 공간에 메모리 주소 #4000을 확보하고 식별자 b를 저장한다. 이제 식별자 a를 찾아서 그 값을 검색해온다. #4000 주소에 #1003 주소를 대입한다. 
3) b를 다시 100이라고 재 할당을 하면, 새로운 메모리 공간 #2345 에 원시값 100을 저장하고 #2345 주소를 #4000에 변수값으로 대입한다. 

대부분의 자바스크립트 책에서 '기본형은 값을 복사하고 참조형은 주솟값을 복사한다'고 설명하고 있다 .내 블로그 설명에서도..하지만 엄밀히 말하자면, 어떤 데이터 타입이든 변수에 할당하기 위해서는 주솟값을 복사해야하기 때문에 자바스크립트의 모든 데이터 타입은 참조형 데이터 일수 밖에 없다. 다만, 기본형은 주솟값을 복사하는 과정이 한번만 일어난다. 뒤에서 볼 참조형은 한단계 더 거치게 된다는 차이가 있다. 

 

 

✅참조형

1) 가변성을 띈다. 변경 가능한 값을 말한다. 

아래 객체 예시를 통해 변수에 객체를 할당하는 과정에 대해서 살펴보자


아래 그림을 살펴보자

원시값을 할당한 변수(age,name) 은 원시값 자체(29,'eunhe') 를 값으로 갖는다. 하지만 객체를 할당한 변수(person) 가 기억하는 메모리주소를 통해 메모리 공간에 접근하면 참조값에 접근할 수 있다.
참조값 :
생성된 객체가 저장된 메모리 공간의 주소, 그 자체이다. 

person.name = 'SeonEunHye' 라고 프로퍼티 값을 변경하게 되면 어떻게 될까?
person 객체의 name 을 'SeonEunHye'라고 할당하면 person 이 바라보고 있는 주소 #1003이 변경되는 게 아닌 기존 내부의 값만 바뀐다. 바로 이 부분 때문에 참조형 데이터는 가변값 이라고 하는 것이다. 
※ 참고로, 참조형 데이터 자체를 변경할 경우는 불변값이고 그 내부의 프로퍼티를 변경할 때만 가변성이 성립된다. 
(참조형 데이터 자체라는 뜻은
var person = {age : 29, name : 'SeonEunhye'} 을
person = {age:35,name:'Ella'} 으로
새로운 객체를 할당하여 값을 직접 변경하는 걸 말한다)

원시값은 앞서 말했듯이 변경 불가능 한 값이므로 원시 값을 갖는 변수의 값을 변경하려면 재할당 외에는 방법이 없다. 하지만, 객체를 할당한 변수(person) 은 재할당 없이 객체를 직접 변경할 수 있다. 재할당 없이 프로퍼티를 동적으로 추가할 수도 있고, 프로퍼티 값을 갱신할 수도 있으며 프로퍼티 자체를 삭제할 수도 있다. 


 

2) 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달이라 한다. 

(참고 : 값을 복사한게 아니라 참조값이 복사되기 때문에, 객체를 가리키는 변수에 변수를 할당하면 값 공유가 일어난다.

밑에 글 펼치면 설명나옴)

따라서, 값공유를 방지하고 독립적인 값을 저장하도록 spread 문법을 쓴다 (밑에 설명 펼쳐보삼)

아래 그림과 같이 person2는 person1을 할당했기때문에 person1의 변수값인 #1003을 저장한다. 따라서, 변수 person1 과 person2는 여전히 같은 객체를 바라보고 있는 상태이다. 


위의 개념을 봤다면 아래와 같이 비교했을 때 왜 true 값이 나오고 false 값이 나오는지 알 수 있을것이다.

위의 그림을 보면 변수에 변수값을 할당할 때 같은 메모리 주소를 바라보고 있기에 true값이 나온다.

 

변수 a 와 b 에 동일한 원시값인 80을 할당한 경우, 자바스크립트 엔진은 최적화를 위해 메모리를 공유하게 된다. 변수 a와 변수 b는 같은 메모리 주소를 참조한다. 

따라서,  "let a = 80, b = a"와 "let a = 80, let b = 80" 둘 다 변수 a와 변수 b는 같은 메모리 주소를 참조한다.

같은 메모리 주소를 바라보고 있어서 true 값이다. 

위의 예제는, 데이터는 person1 과 person2가 같지만 person1과 person2가  다른 메모리주소를 참조하고 있어서 false이다.


2. 얕은 복사 VS 깊은 복사

- 얕은 복사(Shallow Copy)객체를 복사할 때 원본 값과 복사된 값이 같은 참조(=메모리 주소)를 가리키는 것이다.또한, 객체 안에 객체가 있을 경우에 한 개의 객체라도 원본 객체를 참조한다면 얕은 복사라고 볼 수 있다. 얕은 복사 후 해당 변수를 재사용하여 수정한다면 원본 값이 동시에 변하므로 주의가 필요하다. 


- 깊은 복사(Deep Copy)는 복사된 객체가 다른 주소를 참조하며 내부의 값만 복사된다.

 

 


출처

https://curryyou.tistory.com/276

 

[자바스크립트] 콜스택/메모리힙 구조, 데이터 저장/참조 원리

이 글은 자바스크립트의 콜스택/메모리힙에서 데이터가 어떤 방식으로 저장되고 참조되는지를 정리한다. 기본적인 메모리 구조와 변수 생성 원리에 대해서는 아래 글을 꼭 참고(필수) [자바스

curryyou.tistory.com

모던 자바스크립트 Deep Dive : 자바스크립트의 기본 개념과 동작원리

코어 자바스크립트

https://hanamon.kr/javascript-%EB%B3%80%EC%88%98%EC%9D%98-%ED%83%80%EC%9E%85-%EC%9B%90%EC%8B%9C%ED%98%95%EA%B3%BC-%EC%B0%B8%EC%A1%B0%ED%98%95/

 

[JavaScript] 변수의 타입 (원시형과 참조형) - 하나몬

What is Variable type? ⚡️ 변수의 타입 자바스크립트(JavaScript)에는 타입(Type)이라는 개념이 있다. 변수에는 다양한 타입이 있다. 변수에 담을 수 있는 데이터는 숫자나 문자처럼 특정한 형태를 가지

hanamon.kr

https://jae04099.tistory.com/entry/JavaScript-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%B6%88%EB%B3%80%EC%84%B1-%EA%B0%80%EB%B3%80%EC%84%B1

https://joooohee.tistory.com/2

 

[Javascript] 불변객체? 불변성? 그게 뭐에요?!!

불변성이란? 사전적의미 그대로 변하지 아니하는 성질이다. 불변성이라는 개념을 이해하기 위해서는 자바스크립트의 데이터가 처리되는 과정을 이해해야한다. 자, 그럼 그 처리 과정을 대략적

joooohee.tistory.com