JavaScript에서 데이터 타입은 크게 원시형(primitive type)과 참조형(reference type)으로 나눌 수 있습니다. 참조형은 객체(Object)를 기반으로 하며, 메모리에서 값이 아닌 주소(reference)를 참조합니다. 이 때문에 참조형 데이터는 다르게 작동하며, 원시형과는 구별됩니다. 여기서 참조형에 대해 자세히 설명하겠습니다.
1. 참조형의 개념
참조형(reference type) 데이터는 변수에 실제 값을 저장하는 대신, 값이 저장된 메모리 주소를 참조합니다. 이는 객체가 크고 복잡한 데이터를 다룰 수 있도록 합니다.
참조형에는 다음과 같은 데이터 타입이 포함됩니다:
- Object: 일반 객체, 배열, 함수 등
- Array: 배열
- Function: 함수
- Date: 날짜 객체
- RegExp: 정규 표현식
- Map: 키-값 쌍의 컬렉션
- Set: 중복되지 않는 값의 컬렉션
- WeakMap: 키가 객체이고, 가비지 컬렉션이 가능한 Map
- WeakSet: 중복되지 않는 값의 컬렉션이며, 값이 객체이고, 가비지 컬렉션이 가능한 Set
2. 참조형과 메모리
참조형 데이터를 변수에 할당하면, 변수는 실제 값이 아닌 값이 저장된 메모리의 주소를 가리킵니다. 이를 참조(reference)라고 부릅니다.
let obj1 = { name: "Alice" };
let obj2 = obj1;
obj2.name = "Bob";
console.log(obj1.name); // "Bob"
위 예제에서 obj1과 obj2는 동일한 메모리 주소를 참조하기 때문에, obj2를 통해 값을 변경하면 obj1의 값도 변경됩니다.
3. 참조형과 원시형 비교
- 원시형(Primitive Types): 변수에 값 자체가 저장됩니다. 원시형 데이터는 불변(immutable)입니다.(원시형 데이터 자체는 불변이며, 변수에 새로운 값을 할당하면 그 변수는 새로운 값을 참조하게 됩니다.)
- 예: number, string, boolean, null, undefined, symbol, bigint
- 참조형(Reference Types): 변수에 값의 메모리 주소가 저장됩니다. 참조형 데이터는 가변(mutable)입니다.
- 예: Object, Array, Function
let x = 10;
let y = x;
y = 20;
console.log(x); // 10 (원시형은 값 복사)
let objA = { age: 30 };
let objB = objA;
objB.age = 40;
console.log(objA.age); // 40 (참조형은 참조 복사)
4. 참조형의 동작 방식
참조형 데이터는 가변이기 때문에, 같은 객체를 참조하는 여러 변수가 있으면 하나의 변수를 통해 객체를 수정하면 다른 변수에서도 영향을 받습니다.
let person = { name: "John" };
let anotherPerson = person;
anotherPerson.name = "Jane";
console.log(person.name); // "Jane"
이 예제에서는 anotherPerson이 person과 동일한 객체를 참조하고 있어, anotherPerson의 name 속성을 수정하면 person의 name도 함께 변경됩니다.
5. 참조형 데이터의 비교
참조형 데이터를 비교할 때는 메모리 주소를 비교합니다. 따라서 두 객체가 동일한 구조와 값을 가지고 있더라도, 서로 다른 객체라면 비교 시 false가 반환됩니다.
let obj1 = { name: "Alice" };
let obj2 = { name: "Alice" };
console.log(obj1 === obj2); // false (다른 메모리 주소)
하지만 같은 객체를 참조하는 경우 true가 반환됩니다.
let obj1 = { name: "Alice" };
let obj2 = obj1;
console.log(obj1 === obj2); // true (같은 메모리 주소)
6. 얕은 복사와 깊은 복사
얇은 복사(Shallow Copy)는 원본 객체의 주소를 복사하여 값 변경 시 원본 값도 같이 변경합니다. 참조형 데이터를 복사할 때, 단순히 변수에 할당하면 얕은 복사(shallow copy)가 이루어집니다. 얕은 복사는 새로운 객체를 생성하지만, 내부의 참조형 데이터는 같은 메모리 주소를 참조합니다. (단, 아래 예제에 사용된 assign()의 경우 중첩된 객체인 original.b.c 만 주소를 참조하고 있다. original.a의 경우 복사 후 값을 바꾸어도 원본에는 변경되지 않는다. 부분 얇은 참조 예시이므로 참고할 것)
let original = { a: 1, b: { c: 2 } };
let copy = Object.assign({}, original);
copy.b.c = 3;
console.log(original.b.c); // 3 (얕은 복사로 인해 원본이 수정됨)
깊은 복사(Deep Copy)는 객체의 모든 중첩된 값까지 새로 복사하여, 원본 객체와 완전히 독립적인 객체를 만듭니다. 이를 위해서는 재귀적 복사나 JSON.parse(JSON.stringify(obj))와 같은 방법을 사용할 수 있습니다.(단, 복사할 객체에 undefined, function, symbol 등이 포함된 경우 그 값들은 무시되거나 손실될 수 있습니다.)
let original = { a: 1, b: { c: 2 } };
let deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.a = 9;
deepCopy.b.c = 3;
console.log(original); // { a: 1, b: { c: 2 } }; (깊은 복사로 인해 원본이 수정되지 않음)
console.log(deepCopy); // { a: 9, b: { c: 3 } };
7. 참조형의 메모리 관리
참조형 데이터는 가비지 컬렉션(garbage collection)을 통해 메모리가 자동으로 관리됩니다. 참조가 더 이상 존재하지 않는 객체는 메모리에서 해제됩니다. 그러나 순환 참조(circular reference)가 발생하면 메모리 누수(memory leak)가 발생할 수 있습니다.(대부분의 현대 JavaScript 엔진은 순환 참조가 있더라도 객체가 접근 불가능할 때 올바르게 메모리를 해제합니다. 따라서 순환 참조 자체가 반드시 메모리 누수를 일으키는 것은 아니지만, 여전히 주의가 필요합니다.)
function createCircularReference() {
let obj1 = {};
let obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1;
}
이 경우, 가비지 컬렉터가 객체를 메모리에서 해제하지 못할 수 있으므로 주의가 필요합니다.
8. 참조형 데이터의 활용
참조형 데이터는 JavaScript에서 데이터 구조를 다루는 데 매우 중요한 역할을 합니다. 객체를 통해 여러 개의 관련 데이터를 그룹화하거나, 배열을 통해 리스트 형태의 데이터를 관리할 수 있습니다. 함수는 일급 객체로서 다른 함수의 인자로 전달하거나 반환할 수 있으며, 이는 JavaScript의 함수형 프로그래밍 스타일을 가능하게 합니다.
요약
- 참조형 데이터는 메모리의 주소를 참조하며, 객체나 배열과 같은 복잡한 구조를 표현할 수 있습니다.
- 참조형 데이터는 가변이며, 같은 객체를 참조하는 변수들이 있을 경우 그 중 하나를 수정하면 다른 변수에도 영향이 미칩니다.
- 참조형 데이터의 비교는 값이 아닌 메모리 주소를 비교합니다.
- 복사 시 얕은 복사와 깊은 복사 간의 차이를 이해하고 상황에 맞는 방법을 선택해야 합니다.
- 메모리 관리와 가비지 컬렉션, 순환 참조 문제에 대해 이해하고 주의해야 합니다.
이러한 개념을 이해하면 JavaScript에서 객체와 배열 등 복잡한 데이터 구조를 더 효과적으로 다룰 수 있습니다.
'WebDev > JavaScript' 카테고리의 다른 글
[기초] JavaScript 컨트롤 구조(Control Structure) (2) | 2024.09.06 |
---|---|
[기초] JavaScript DOM이란? (0) | 2024.09.05 |
[기초] JavaScript Destructuring (2) | 2024.09.02 |
[기초]JavaScript 스프레드 연산자(Spread Operation) (0) | 2024.08.30 |
[기초]JavaScript 화살표 함수(Arrow Function) (0) | 2024.08.29 |