티스토리 뷰
개념/2025 학습
원시값(Primitive Value)과 참조값(Reference Value), 객체 복사(얕은 복사 Shallow Copy, 깊은 복사 Deep Copy)
주섬이 2025. 2. 8. 20:15반응형
원시값(Primitive Value)과 참조값(Reference Value), 객체 복사(얕은 복사 Shallow Copy, 깊은 복사 Deep Copy)
자바스크립트에서의 데이터는 원시값(Primitive Value)과 참조값(Reference Value) 두가지 유형으로 나눌수 있다.
이 두 유형은 메모리에 저장되는 방식과 복사되는 방식이 다르다.
원시값(Primitive Value)
- 종류로는 string, number(Infinity, NaN 포함), boolean, undefined, null, symbol, bigint이 있다.
- 값 자체를 저장하며, 변수에 할당할 때 새로운 메모리 공간에 저장한다. (때문에 불변하다. = 한번 생성된 값을 변경할 수 없다.)
- 값을 복사하게되면 새로운 메모리 공간에 할당된다. (독립적인 값)
let a = 10;
let b = a; // a의 값을 b에 복사 (새로운 메모리 공간 할당) b = 20;
console.log(a); // 10 (원래 값 유지)
console.log(b); // 20 (새로운 값)
a의 값을 b에 복사할 때 새로운 메모리 공간이 생성되었기 때문에 b의 값을 변경해도 a에 영향을 주지 않는다.
참조값(Reference Value)
- 종류로는 Object, Array, Function, Set, Map, WeakSet, WeakMap 이 있다.
- 메모리 주소(참조)를 저장하는 데이터 타입이며, 변수에는 객체의 메모리 주소(참조값)가 저장된다.
- 값을 복사하게되면 메모리 주소를 공유(참조)하므로 원복 객체도 영향을 받는다. (얕은 복사)
let obj1 = { name: "Alice" };
let obj2 = obj1; // 같은 메모리 주소를 공유 (얕은 복사)
obj2.name = "Bob"; // obj2를 변경하면 obj1도 영향을 받음
console.log(obj1.name); // "Bob"
console.log(obj2.name); // "Bob"
obj1과 obj2는 같은 메모리 주소를 가리키고 있기 때문에, 한쪽을 변경하면 다른 쪽도 변경된다.
비교
특징 | 원시값 (Primitive) | 참조값 (Reference) |
저장 방식 | 값 자체 저장 | 메모리 주소(참조값) 저장 |
복사 방식 | 새 메모리 공간에 값 복사 (독립적) | 같은 주소를 공유 (얕은 복사) |
변경 가능 여부 | 불변(Immutable) | 변경 가능(Mutable) |
얕은 복사 (Shallow Copy)
객체를 복사할때 메모리주소(참조)만 복사해서 복사 시 같은 객체를 가리키게된다.
Object.assign()이나 spread 연산자 등을 사용할 경우 얕은 복사이다.
let obj1 = { name: "Alice" };
let obj2 = { ...obj1 }; // 얕은 복사
obj2.name = "Bob";
console.log(obj1.name); // "Alice" (영향 없음)
console.log(obj2.name); // "Bob"
단, 객체 내부에 또 다른 객체가 있을 경우(중첩 객체)에는 내부 객체는 같은 참조를 공유하여 서로에게 영향을 준다.
let obj1 = { user: { name: "Alice" } };
let obj2 = { ...obj1 }; // 얕은 복사
obj2.user.name = "Bob";
console.log(obj1.user.name); // "Bob" (내부 객체는 공유됨)
console.log(obj2.user.name); // "Bob"
깊은 복사(Deep Copy)
객체의 모든 값을 새로운 메모리 공간에 복사하여 원본과 독립적인 객체를 생성하는 방법이다.
JSON.parse(JSON.stringify(obj)), structuredClone() 등을 사용할 경우 깊은 복사이다.
let obj1 = { user: { name: "Alice" } };
let obj2 = JSON.parse(JSON.stringify(obj1)); // 깊은 복사
obj2.user.name = "Bob";
console.log(obj1.user.name); // "Alice" (영향 없음)
console.log(obj2.user.name); // "Bob"
JSON.stringify() 방식은 undefined, Symbol, Function을 복사하지 못하는 단점이 있다.
라이브러리 사용(lodash DeepCole())이나 순회하여 복사하는 방법도 있다.
import lodash from "lodash";
const obj1 = { name: "Alice", address: { city: "Seoul" } };
const obj2 = lodash.cloneDeep(obj1);
obj2.address.city = "Busan";
console.log(obj1.address.city); // "Seoul" (원본 영향 없음 ✅)
console.log(obj2.address.city); // "Busan"
최신 브라우저는 structuredClone()를 사용할 수 있다.
let obj2 = structuredClone(obj1);
정리
구분 | 원시값 (Primitive) | 참조값 (Reference) |
메모리 저장 방식 | 값 자체 저장 | 메모리 주소 저장 |
변수 할당 시 | 값이 복사됨 (새로운 공간) | 주소가 복사됨 (같은 객체 참조) |
불변성(Immutable) | ✅ (변경 불가) | ❌ (변경 가능) |
복사 방식 | 값이 독립적 | 같은 객체를 공유 |
예제 | let a = 10; let b = a; | let obj2 = obj1; |
그렇다면 언제 어떤 방식을 사용해야할까?
방법 | 장점 | 단점 | 사용 추천 |
얕은 복사 (Object.assign(), spread 연산자) | 빠르고 간단함 | 내부 객체가 공유됨 | 단순한 객체 |
JSON.stringify() + JSON.parse() | 간단한 깊은 복사 | undefined, Symbol, Function 복사 불가 | 기본 객체 |
structuredClone() | 최신 방법, 빠르고 안전함 | Node.js 미지원 | 브라우저에서 안전한 깊은 복사 |
_.cloneDeep() (lodash) | 모든 타입을 안전하게 복사 | 라이브러리 필요 | 복잡한 객체, 대규모 프로젝트 |
반응형
'개념 > 2025 학습' 카테고리의 다른 글
이벤트 루프와 Web APIs의 관계 (0) | 2025.03.06 |
---|---|
이벤트 위임(Event Delegation)과 성능 최적화 (0) | 2025.02.27 |
프로토타입과 프로토타입 체인 (0) | 2025.02.25 |
프로미스 체이닝 (Promise Chaining) (0) | 2025.02.12 |
자바스크립트 이터러블(iterable)과 이터레이터(iterator) (0) | 2025.02.06 |
자바스크립트 구조분해할당 (Destructuring) (0) | 2025.02.03 |
자바스크립트 실행 컨텍스트(Execution Context) (2) | 2025.01.30 |
이벤트 루프와 비동기 처리 + 가비지 컬렉션과의 연관 (2) | 2025.01.23 |