[JavaScript] 원시값과 참조값, 얕은 복사와 깊은 복사

Byeonghyeon·2025년 1월 12일

공부

목록 보기
4/21

원시값과 참조값

  • 원시값 : String, Number, Boolean, null, undefined, Symbol 등
  • 참조값 : Array, Object, Function 등

원시값은 변수에 저장된 실제 값에 직접 접근할 수 있는 단순한 데이터. 하나의 값에 대한 정의가 절대 변하지 않는 불변성을 갖고 있다.

참조값은 원시값을 제외한 모든 타입이 참조값이며, 참조값의 데이터 자체는 별도의 메모리 공간에 저장되고 변수에 할당 시 데이터의 값이 아닌 데이터에 대한 메모리 공간의 주소가 저장된다.
크기가 고정적으로 정해져있지 않고, 변수에는 데이터에 대한 참조만이 저장된다.

여기서 원시값의 불변성에 조금 의아할 수 있다.

let num = 1;
num = 5;

이런 코드를 작성했다고 가정해보자.

얼핏 생각해보면, num이라는 변수의 값은 1이었는데 이후 5로 변했다고 생각할 수 있을 것이다. 하지만 이것은 원시 값 자체를 수정하는 것이 아니라 새 메모리 공간에 재할당한 원시 값을 저장한 것이다.

즉 처음에 num이라는 변수에 1이라는 값이 할당되면 변수는 1이 할당된 메모리 주소a를 참조하다가, 5라는 값으로 재할당되면, 새로운 메모리 공간을 확보해 재할당한 값(여기서는 5)을 저장한 후, 변수가 참조하던 메모리 공간의 주소를 변경하는 것이다.

let num1 = 1;
let num2 = 1;
num === num2 // true

원시 값은 실제 값 자체를 비교하기 때문에 다른 변수에 같은 값을 지정한 후 비교하면 두 값이 같다.

반면 참조값은 여러 값으로 구성되는 메모리에 저장된 객체이며, 변경이 가능하다.

let player = {
	name: 'Stroud',
    number: 9
}
player.number = 7;

참조 값을 할당한 변수 player에 새로운 값을 재할당하면, 메모리 안의 참조 값이 변경되며 메모리 주소에는 영향을 주지 않는다.

let player1 = {
	name: 'Stroud',
    number: 7
}

let player2 = {
	name: 'Stroud',
    number: 7
}

player1 === player2; // false 

참조 값은 값 자체가 아닌 메모리 주소를 비교하기 때문에 다른 객체에 같은 값을 지정한 후 비교하면 두 값이 다르다.

얕은 복사와 깊은 복사

얕은 복사(Shallow copy)

얕은 복사는 객체의 1단계 값만 복사한다.
즉, 객체 내부의 참조 타입(배열, 객체 등)참조 값(메모리 주소)만 복사된다.

복사된 객체는 원본 객체와 같은 참조를 공유한다.

복사본에서 참조 타입의 데이터를 변경하면 원본 객체도 영향을 받는다.

예시
const original = { name: "Alice", details: { age: 25 } };

const shallowCopy = { ...original }; // 얕은 복사

shallowCopy.name = "Bob"; // 원본 객체에는 영향 없음
shallowCopy.details.age = 30; // 원본 객체의 details도 변경됨

console.log(original); // { name: "Alice", details: { age: 30 } }
console.log(shallowCopy); // { name: "Bob", details: { age: 30 } }

Object.assign() 또는 스프레드 연산자 (...)를 통해 얕은 복사를 할 수 있다.

깊은 복사(Deep copy)

깊은 복사는 객체의 모든 값을 재귀적으로 복사하여 원본 객체와 독립적인 복사본을 생성한다.
즉, 참조 타입도 새롭게 메모리에 복사된다.

복사된 객체는 원본 객체와 참조를 공유하지 않는다.

복사본을 수정해도 원본 객체에 영향을 미치지 않는다.

예시
const original = { name: "Alice", details: { age: 25 } };

const deepCopy = JSON.parse(JSON.stringify(original)); // 깊은 복사

deepCopy.name = "Bob"; // 원본 객체에는 영향 없음
deepCopy.details.age = 30; // 원본 객체에는 영향 없음

console.log(original); // { name: "Alice", details: { age: 25 } }
console.log(deepCopy); // { name: "Bob", details: { age: 30 } }

JSON.stringify(obj)를 이용해 복사하는 방법과 lodash의 cloneDeep을 이용해 복사하는 방법이 있다.

0개의 댓글