참조 타입(Reference Type)과 객체 메모리 관리
지금까지 number, string, oddball (null, undefined, boolean) 타입들의 메모리 처리 방식을 살펴보았습니다. 이번 게시글에서는 참조 타입(Reference Type)에 대해 알아보겠습니다.
참조 타입의 대표적인 예는 객체(Object) 입니다. 개발 중 객체를 다른 변수에 할당했을 때, 기존 객체와 의도치 않게 연결되는 경험을 해본 적이 있을 겁니다. 이는 원시 타입과는 다른 동작 방식 때문인데요, 왜 이러한 일이 발생하는지 크롬 개발자 도구의 메모리 탭을 통해 자세히 살펴보겠습니다.
class ObjectSnapshot {
constructor() {
this.object = {
string1: 'a'.repeat(10),
string2: 'East',
number1: 2 ** 30,
number2: 1,
null: null,
undefined: undefined,
true: true,
false: false,
object2: {
string3: 'East',
number3: 1,
object3: {
null2: null,
undefined2: undefined,
true2: true,
false2: false,
}
}
}
this.copyObject = this.object.object2;
this.copyObject.number3 = 10;
this.copyObject2 = this.object.object2;
this.copyObject2 = 'reset copyObject2';
}
}
위 코드를 크롬 개발자 도구에서 힙 스냅샷(Heap Snapshot)을 찍어보면, 객체 내부의 각 값들(string
, number
, oddball
)은 객체 외부와 동일하게 처리되는 것을 확인할 수 있습니다. 작은 숫자는 smi
(small integer), 큰 숫자는 heap number
로 처리되고, 문자열은 동적 또는 정적으로 관리됩니다.
객체(object
)는 메모리 주소가 할당되고, 내부 값들은 key
가 표시되지만 실제로는 메모리 주소에 각 값들이 할당되어 있습니다. 이를 조금 더 구체적으로 표현하면, 다음과 같이 해석할 수 있습니다.

ObjectSnapshot
object
::{@542297(string1), @378139(string2), @542299(number1), @558203(number2), @71(null), @67(undefined), @73(true), @75(false), @542293(object2)} @542291
ObjectSnapshot2
object
::{@542325(string1), @378139(string2), @542327(number1), @558203(number2), @71(null), @67(undefined), @73(true), @75(false), @542323(object2)} @542321
해석:
각 ObjectSnapshot
인스턴스에는 object(@542291 / @542321)
가 존재하며, 이 메모리 주소들에는 각 프로퍼티의 메모리 주소가 담겨 있습니다. 다시 말해, 객체 변수에 할당된 메모리 공간에는 그 객체가 담고 있는 값들이 아니라, 그 값들이 저장된 메모리 주소들이 들어 있습니다. 자바스크립트에서 하나의 메모리 주소에는 하나의 값만 저장될 수 있기 때문에, 객체는 내부적으로 각 속성 값들이 따로 관리되고, 이를 참조하는 주소를 저장하는 구조를 갖고 있습니다.
그럼 object.object2
의 값을 초기값으로 선언한 copyObject
와 copyObject2
는 어떻게 되어있을까요?
ObjectSnapshot1
copyObject
::{.. 각 값들의 메모리 주소} @542293copyObject2
::"reset copyObject2" @539065
ObjectSnapshot2
copyObject
::{.. 각 값들의 메모리 주소} @542323copyObject2
::"reset copyObject2" @539065

copyObject와 copyObject2의 동작 분석 (ObjectSnapshot1 기준)
- copyObject의 동작
copyObject
는object.object2
의 메모리 주소를 할당받아 같은 객체를 참조합니다. (@542293)- 따라서
copyObject.number3 = 10
으로 값을 변경하면,object.object2.number3
도 변경됩니다. 이는 두 변수가 동일한 메모리 주소를 참조하고 있기 때문입니다.
- copyObject2의 동작
- 처음에는
copyObject2
도object.object2
와 동일한 메모리 주소를 참조하고 있었습니다. (@542293) - 하지만
"reset copyObject2"
로 재할당된 후에는 더 이상 같은 객체를 참조하지 않습니다. 즉,copyObject2
는 새로운 값("reset copyObject2"
)을 가리키게 되며,object.object2
와는 별개의 메모리 주소를 갖게 됩니다.
- 처음에는
이처럼 자바스크립트에서 객체를 다룰 때는 객체가 메모리 주소를 참조하는 특성에 주의해야 합니다. 변수 간 객체를 공유할 경우, 객체의 속성 값을 수정하면 해당 객체를 참조하는 모든 변수에서 그 변경이 반영되지만, 새로운 값으로 재할당하면 독립적인 변수가 됩니다.
결론
참조 타입인 객체는 변수에 메모리 주소가 할당되며, 이 메모리 주소는 객체 내부 값들을 참조합니다. 이로 인해 하나의 변수를 통해 객체를 수정하면 그 객체를 참조하는 다른 변수에도 변경 사항이 반영됩니다. 그러나 해당 변수에 새로운 값을 재할당하면, 그 변수는 더 이상 원래 객체와 연결되지 않고, 새로운 값을 독립적으로 가리키게 됩니다.
그동안 참조타입과 원시타입에 대해 메모리 관점에서 바라보며 알아보았습니다. 각 부분에 대해서는 최대한 공식 정보를 참고하려고 하였으나 그러한 정보를 찾지 못한 부분들에는 개인적인 해석이 포함되어있어 잘못된 정보가 있을 수 있습니다. 잘못된 부분이 있거나 궁금한 점이 있을 경우 댓글 부탁드립니다.
원시 타입과 참조 타입 시리즈
- V8 엔진의 숫자 처리 방식
- V8 엔진의 문자열 처리 메커니즘
- V8 엔진의 Oddball 타입
- V8 엔진의 참조 타입과 기타 다른 타입들 (본 게시글)
'Javascript' 카테고리의 다른 글
자바스크립트의 this 알아보기 (2) | 2024.11.09 |
---|---|
원시 타입과 참조 타입 - 3.V8 엔진의 Oddball 타입 (0) | 2024.10.21 |
원시 타입과 참조 타입 - 2. V8 엔진의 문자열 처리 메커니즘 (2) | 2024.10.17 |
원시 타입과 참조 타입 - 1. V8 엔진의 숫자 처리 방식 (0) | 2024.10.17 |