객체와 배열의 참조 및 복사

chosey·2022년 11월 22일
0

JavaScript

목록 보기
1/1

객체 또는 배열과 원시 데이터의 근본적인 차이점 중 하나는 객체와 배열은 “참조에 의해” 저장과 복사가 되는 반면, 원시 데이터( 문자열, 숫자, 부울 등)은 항상 “전체 값으로” 복사된다는 것입니다.

javascript.info의 글을 참고하여 작성하였습니다.


원시 데이터의 복사

먼저 일반적인 데이터를 복사하는 과정을 살펴보겠습니다.

let string = "Hello, world !";
let copy = string;

stringcopy 두 개의 변수가 각각 하나의 상자이고, 문자열이 서류 한장이라고 가정하면, copy 상자는 string 상자에 담겨있는 Hello, world ! 서류를 복사하여 담습니다.

원시 데이터들은 간단합니다. 그냥 기존 값을 복사하여 저장하는 것.


그럼 객체와 배열은?

원시 데이터와는 다르게 객체나 배열이 할당된 변수는 해당 그들 자체가 아닌 그들이 있는 메모리상의 “메모리 주소”
즉, 대한 “참조”를 저장합니다.

이 글에서는 객체의 참조 및 복사만을 다루겠습니다.

객체의 할당

객체의 복사를 살펴보기 위해서는 먼저 객체가 선언된 변수가 무엇을 의미하는지 알아보아야 합니다.

아래의 user 변수는 객체 `{ name : “choi”, age : 24 }` 가 저장된 메모리를 참조합니다.

let user = {
	name : "choi",
	age : 24
};

즉, 객체 자체가 할당되는 것이 아니라 해당 객체에 대한 참조가 할당되는 것인데, user 변수는 { name : "choi", age : 24 } 로 정의된 객체라는 아파트에 접근할 수 있는 공동 현관 이라고 생각하면 됩니다.

실제로 JavaScript 엔진은 객체의 name 속성을 가져올 때, user 가 어떤 객체를 가리키는지, 무엇이 있는지 확인하고 해당 객체에 대한 작업을 수행합니다.

위의 그림을 다시 한번 아파트와 공동 현관, 집으로 비유하자면

Object라는 아파트(객체)

user 라는 이름의 공동 현관(변수)을 만들어

name, age 이라는 각각의 집(속성)들어가겠다(접근하겠다).

user.nameuser 라는 공동 현관(변수)을 가진 아파트(객체)name 이라는 집(속성)을 열어보겠다. 라는건
즉, user라는 변수로 메모리상에 있는 해당 객체에 접근하고, name이라는 키를 통해 "choi" 값을 가져오겠다. 라는 의미입니다.

위의 내용이 중요한 이유는 user 변수를 복사하면 아파트(객체) 자체가 복사되는 것이 아닌, 공동 현관(객체의 참조가 저장된 변수)이 하나 더 만들어집니다. 즉, C의 포인터와 비슷한 객체의 참조가 복사되는 것입니다.


객체를 선언한 변수를 또 다른 변수에 할당

아래 두 개의 변수는 각각 { name : "choi", age : 24 }; 라는 객체 참조를 저장합니다.

let user = { name : "choi", age : 24 };
let admin = user; // admin이라는 공동 현관이 하나 더 만들어집니다. 객체 참조 복사

위의 코드를 아래의 비유와 그림으로 표현하였는데

Object 라는 아파트(객체)
user 라는 공동 현관문(변수)
admin 이라는 이름으로 하나 더 만들어서
name, age 집(속성)에 들어가겠다(접근하겠다).

따라서 객체의 name 속성에 접근할 때, user.name , admin.name 두 방법중 어떤 것을 사용하든 객체의 name 속성에 접근할 수 있습니다.
그리고 user.name = "anything" 처럼 name 의 값이 변경된 이후, admin 으로 객체에 접근하면 변경된 값인 "anything" 으로 나타납니다.


객체 또는 배열을 복사할 때 주의해야 하는 이유

앞의 내용으로 객체나 배열이 선언된 변수 또는 상수는 메모리상에 있는 객체나 배열 그 자체가 아닌 해당 메모리의 참조라는 것을 알았습니다.
따라서 참조의 문제점은 원하지 않은 객체의 데이터 변경으로 이어질 수 있습니다.


그래서 객체를 복사하려면?

객체를 복사한다는 것은 해당 객체가 가지고 있는 속성들을 복사한다는 것인데, 이는 Object.assign() 메소드로 위의 문제점을 완벽히 해결할 수 있고, 간단한 객체 속성 복사는 점 3개로 이루어진, ... 스프레드 연산자를 사용하여 복사할 수 있습니다.

Object.assign() 메소드로 복사

const person = {
	name : "choi",
	age : 24
};

person.name = "king_god_general" // name 속성의 값이 변경되어도

const nextPerson = Object.assign(person); // nextPerson의 name: "choi"가 출력된다.

... 스프레드 연산자로 복사

const person = {
	name : "choi",
	age : 24
};

const nextPerson = { 
	...person
} 
// person이 가리키는 객체를 참조하는 것이 아닌 객체의 내용이 복사됨
profile
chosey

0개의 댓글