이 글은 코어자바스크립트 특강 내용을 정리한 글입니다.
자바스크립트는 크게 2가지 타입으로 나뉜다.
참조형 타입으로는 대표적으로 객체가 있다. 그리고 객체의 하위의 배열, 함수, 정규표현식이 있다.
이렇게 구분하는 이유는??
왜 구분 해야하는지??
어떤차이가 있는지??
에 대한 궁금증을 해결하기 위해서는 각 데이터 타입이 어떻게 메모리에서 동작되는지를 보면 알 수 있다.
각각의 데이터 타입의 변수가 어떻게 할당되는지 보자.
let a;
우선 변수명(혹은 식별자, 이하 변수)과 변수가 가리키는 값을 저장하기 위해 메모리가 할당되어지고 변수명(식별자)가 저장된다.
let a;
a = 'abc';
값 abc가 메모리에 할당이 된다.
변수 a가 저장된 메모리에 값(abc)가 저장된 메모리 주소를 저장한다.
(변수a가 저장된 메모리가 값을 가리킨다.)
let a;
a = 'abc';
a = 'abcdef';
값 abcdef가 메모리에 할당된다.
변수 a가 가리키는 값의 주소가 abcdef가 저장된 메모리 주소로 바뀐다.
여기서 중요!
a
의 값을abc
에서abcdef
바꾸었는데 5004번 메모리에 있는abc
값을 바꾸지 않고 5005번 메모리를 새로 할당해서abcdef
값을 넣은후 변수a
가 5005번 메모리를 가리키게 한다.즉,
기본형 타입 데이터 변수는 재할당 할때 가리키는 값을 바꾸지 않고
새로운 메모리에 값을 할당하여 변수가 가리키는 값의 주소를 바꾼다.
전체 코드와 메모리 처음 상태
let obj = {
a: 1;
b: 'bbb';
};
obj.a = 2;
객체 선언과 할당
let obj = {
...
};
변수명과 값을 가리키는 메모리주소를 할당하고 변수명을 저장한다
프로퍼티를 참조하는 참조용 메모리를 할당한다. 이 메모리는 프로퍼티가 저장된 주소를 가리킨다.
객체의 첫번째 프로퍼티 할당
let obj = {
a: 1;
...
};
프로퍼티a
가 할당이 되고 값 1이 저장된 주소를 가리킨다.(변수가 할당되는 구조와 같다.)
객체의 두번째 프로퍼티 할당
let obj = {
a: 1;
b: 'bbb';
};
프로퍼티b
가 할당이 되고 값 bbb
가 저장된 주소를 가리킨다.
완료
최종적으로 obj
가 참조용 메모리(5002)를 가리킨다.
객체의 프로퍼티의 값 수정
obj.a = 2;
obj.a의 값을 확인한다.
여기서 중요!
기본형 타입 변수와 달리 참조하는 변수가 한 단계(obj.a)가 더 있기 때문에 obj가 가리키는 주소값은 바뀌지 않는다.
단 obj.a
는 기본형 타입 프로퍼티이므로 obj.a
가 가리키는 주소값은 바뀐다.
즉,
참조형 타입 변수의 프로퍼티 값을 재할당 할 때 변수가 가리키는 값의 주소는 바뀌지 않는다.
단, 참조형 변수 자체를 재할당 하면 해당 변수가 가리키는 값의 주소는 바뀐다.
obj.a = 1;
는 obj가 가리키는 주소는 그대로이고 obj.a가가리키는 값의 주소가 바뀌는것
obj = 1;
는 obj가 가리키는 값의 주소가 바뀐다.
이번에는 객체 안에 배열타입의 변수를 알아보자.
전체코드와 메모리 초기상태
let obj = {
x: 3;
arr: [3, 4];
};
obj.arr = 'str';
객체의 기본형 타입 프로퍼티 할당
let obj = {
x: 3;
...
};
여기 까지는 위에 내용과 동일하다.
객체의 참조형 타입(배열) 프로퍼티 할당
let obj = {
x: 3;
arr: [3, 4]; // 여기
};
프로퍼티 arr를 할당한다.
arr가 참조하는 메모리를 할당한다. 해당 메모리는 8104부터 쭉 메모리를 가리킨다.
객체와 비슷하게 인덱스를 저장하고 해당 인덱스가 가리키는 값의 주소를 저장한다.
arr가 5004 메모리를 가리킨다.
수정
obj.arr = 'str';
5006번에 새로운 값(str)을 할당하고 arr(7104)가 5006을 가리키게 한다.
이때 5004번 메모리와 8104, 8106 메모리는 참조 되지 않기 때문에 Galbage Collecting인된다.
이번에 각각의 데이터 타입의 변수가 어떻게 복사가 되는지 알아보자.
let a = 10;
let b = a;
b는 a가 가리키는 값의 주소를 똑같이 가리킨다.
let obj1 = {c: 10, d: 'ddd'};
let obj2 = obj1;
obj2는 obj1이 가리키는 레퍼런스의 주소(5003)를 똑같이 가리킨다.
기본형 타입 변수의 값 수정
b = 15;
15의 값을 갖는 메모리(5004)가 새로 할당이 되고 b가 이 주소를 가리킨다.
참조형 타입 변수의 수정
obj2.c = 20;
메모리에 20(5005)이 할당되고 obj.c가 이 주소를 가리킨다.
여기서 다시 중요!
기본형 타입 변수들이 가리키는 주소는 바뀌었는데
참조형 타입의 변수가 기리키는 주소는 바뀌지 않았다.
기본형 타입 변수는 재할당 할때 가리키는 값을 바꾸지 않고 새로운 메모리에 값을 할당하여 변수가 가리키는 값의 주소를 바꾼다.
참조형 타입 변수는 재할당 할 때 변수가 가리키는 값의 주소는 바뀌지 않는다.
기본형 타입 데이터들을 메모리에 한번 만들어지면 다시 재사용이 된다.
const a = 3;
const b = [3, 4];
3이 메모리에 할당이 되었는데
a와 b 모두 메모리에 1개 할당 되어있는 3을 가리킨다.
이렇게 가능하게 한것이 런타임(엔진)에서 그렇게 가능하도록 하게 했기 때문이다.
기억하자! 1개의 기본형 타입 데이터는 딱 1개만 생성된다.
값을 재할당 할때는 기존의 값이 저장된 메모리에 새로운 값으로 수정되는게 아니다.
새로운 값이 저장된 메모리를 새로 할당하고 기존값과 연결을 끊고 새로운 값과 연결을 한다.
이때 기존의 값은 참조가 끊기게 되고 참조되지 않는 값은 Galbage Collecting이된다.
기본형 타입 변수는 재할당 할때 가리키는 값을 바꾸지 않고 새로운 메모리에 값을 할당하여 변수가 가리키는 값의 주소를 바꾼다.
참조형 타입 변수의 프로퍼티를 재할당 할 때 변수가 가리키는 값의 주소는 바뀌지 않는다.
단, 참조형 변수 자체를 재할당 하면 해당 변수가 가리키는 값의 주소는 바뀐다.
참고
C/C++에서는 메모리 관리를 프로그래머가 직접 해주어야 한다.
하지만 파이썬, 자바스크립트, 자바, Go와 같은 언어들에서는 개발자가 메모리를 할당하고 해제하는것을 신경 쓸 필요가 없다.
Garbage Colletor라는 도구가 메모리 해제를 알아서 해주기 때문이다.
Garbage Colletor 사용이 끝난 객체를 알아서 메모리 공간에서 지워주는 도구이다.
Garbage Colletion 메모린를 해제하는 주요 개념
추가