<자바스크립트>가변값과 불변값 / 깊은 복사와 얕은 복사

Woongbee Park·2022년 8월 18일
0

이 글은 책 <코어 자바스크립트> -정재남 (위키북스 출판)
을 읽고 정리한 글입니다.




자바스크립트에는 2가지 데이터 타입이 있다.
가변값과 불변값.
이는 기본형 데이터(불변값), 참조형 데이터(가변값) 로 불리기도 한다.
말 그대로 값이 변하는 것과 변하지 않는 것으로 분류된다는 말인데, 왜 저렇게 불리게 됐을까를 설명하는 글이다.
이를 알기 위해서는 일단 메모리에 데이터가 저장되는 방식을 알아야 한다.
let a=10;

식별자 a 에 데이터 10을 할당했다.
메모리에서는?

  1. 메모리에 공간을 확보한 뒤, 식별자의 이름 a를 저장한다.
  2. 메모리에 공간을 확보한 뒤, 데이터 10을 저장한다.
  3. 식별자가 저장된 메모리(1001)에 데이터가 저장된 메모리 주소(1006)를 연결한다.

그렇다면, 같은 식별자에 다른 데이터를 재할당하면 어떻게 될까?
식별자 a에 20을 재할당 해보자.

a =20;

메모리는 새로운 데이터 20을 저장하기 위한 메모리 공간을 확보하고
데이터 20을 저장한다. 그리고 20이 저장된 메모리 주소를(1007) 식별자 a가 저장된 메모리와 연결한다.
그러면 1006번지에 저장된 데이터 10은 아무도 참조하지 않으므로,
가비지 컬렉터에 의해 삭제될 것이다.


이렇게, 메모리에 한 번 저장된 값은 바뀌지 않는다.
데이터를 변경하고 싶으면 새로운 메모리에 값을 저장해야 한다.

1006번지에 10이라는 데이터를 다른 값으로 변경할 수 없다.
위에서 보이듯이, 식별자 a에 저장할 데이터를 변경하고 싶으면 새로운 메모리 영역에 새값을 저장한 후 1001번지가 참조하는 메모리 주소를 바꾸어 주어야 한다. 그래서 불변값이라고 부른다.

1006번지에 있는 데이터 10은 아무도 참조하지 않아 가비지 컬렉터의 대상이 되거나, 혹은 다른 식별자가 10이 라는 데이터를 저장한다면 그 식별자가 저장된 메모리가 1006번지를 참조하게 될 것이다.




자 그렇다면 대표적인 참조형 데이터 <객체>가 메모리에 저장되는 방법을 보자.

let a={
 name:"숙희",
 gender:"여성"
};

위 그림의 화살표를 번호 순서대로 따라가며 이해하면 된다.
불변값 데이터를 저장하는 방식과 동일한 방법으로,
한번 더 반복한다.


1. 메모리 공간 확보 후, 식별자 이름 a를 저장(1001)
2. 객체의 프로퍼티 이름들이 저장될 공간의 주소를 저장(1006)
3. 프로퍼티 이름들을 저장한 후,(1013,1014)
4. 프로퍼티 값이 저장된 메모리 주소와 연결 (1007,1008)


이제 프로퍼티 값을 변경해보자

let a={
 name:"숙희",
 gender:"남성"
};

기본형 데이터를 재할당때와 똑같다.
새로운 메모리 영역에 새값을 저장한 후,(1004)
식별자가 저장된 메모리(1014)에서 참조 메모리 주소만 변경 해주면 된다.

여기서 주목해야 할 점은,
식별자 a가 참조하고 있는 메모리 주소는 변하지 않는다는 것이다.
마치 새로운 메모리에 새값을 저장한 게 아니라, 최초의 값이 저장된 메모리에서 값을 지우고, 그 자리에 새값을 저장한것처럼 보인다. 그래서 이를 가변값이라고 부른다.



그러니까 사실 모든 데이터는 불변값이다.

메모리에 저장 된 데이터를 변경할 때,
그 값을 지우고 난 뒤 새로 저장하는게 아니라 무조건 새로운 메모리 영역에 값을 새로 저장한 뒤, 식별자에 연결된 메모리 주소만 바꿔주는 것이기 때문이다.



여기서 깊은 복사와 얕은 복사가 왜 구분되는지도 추론해볼 수 있다.
얕은 복사는 식별자에 저장된 메모리 주소 참조값 까지만 복사하는 거고,
깊은 복사는 식별자에 저장된 메모리 주소 참조값 + 참조된 메모리 주소를 따라가서 그 곳에 저장된 프로퍼티 값을 참조하는 메모리 주소까지 싹 다 복사하는 것을 말한다.



++왜 식별자와 데이터를 나누어 저장할까 라는 의문이 생길 수 있는데,
이는 데이터 변환을 쉽게 하기 위해서 이다. 예를 들어 변수 a에 숫자 10을 저장했다가, 문자열 "숙희"를 재할당 하는 경우를 생각해보자.

let a=10;
a="숙희";

다들 잘 알다시피, 숫자를 저장하기 위한 메모리 공간과 문자열을 저장하기 위해 필요한 메모리 공간은 다르다. 만약 식별자랑 데이터값을 같이 저장해놨는데 데이터값이 바뀌어서 더 많은 메모리가 필요해지면??
그 뒤에 저장된 메모리들이 주루룩 뒤로 밀려야하는 비효율적인 상황이 발생한다.
근데 이처럼 메모리에 식별자 영역과 데이터 영역을 나누어 따로 저장한다면, 데이터가 변경되도 다른 새로운 자리를 찾아서 저장한 뒤, 식별자 영역에는 메모리 참조값만 변경해주면 되니까 간단하다.

profile
나는야 개발자

0개의 댓글