[JS] 원시 타입(Primitive Type)과 참조 타입(Reference Type)의 변수 복사 비교

JeungJoo Lee
CrocusEnergy
Published in
4 min readSep 17, 2020

이번 시간에는 원시타입의 변수와 참조 타입의 변수를 복사했을 때 어떠한 차이점이 있는지 살펴볼 것이다.

원시 타입과 참조 타입의 변수 복사

let a = 10; 
let b = a;
let obj1 = { c: 10, d: 'ddd' };
let obj2 = obj1;

먼저 변수의 선언과 변수의 복사에 대한 코드를 위에서 확인할 수 있다. 원시형 타입과 참조형 타입 동일하게 새로운 변수를 만들어 값을 선언한 기존 변수를 할당하였다. 여기까지는 원시형이든 참조형이든 코드 상으로는 값의 차이가 있을 뿐 동일해 보인다.

변수 복사 후 값 변경 하기

아래 코드는 위의 코드의 연장선 상의 코드로 복사된 변수의 값 또는 복사된 변수 오브젝트의 프로퍼티의 값을 변경하는 것이다.

let a = 10;
let b = a;

let obj1 = { c: 10, d: 'ddd' };
let obj2 = obj1;

b = 15;
obj2.c = 20;

b 의 원시형 타입은 10 이 할당되어 있는 a 를 b 에 할당 하였고 obj2 는 obj1 에 Object 타입으로 선언된 값을 할당하였다. 그리고 각각 값을 15와 obj2 의 c 프로퍼티 값을 20으로 변경하였다. 그 후, 위의 각각 원시 타입의 값 a, b 를 출력하고 obj1, obj2 를 출력하면 아래와 같은 결과를 확인할 수 있을 것이다.

// 원시타입의 결과
a -> 10
b -> 15
// 참조타입의 결과
obj1 -> { c: 20, d: 'ddd' }
obj2 -> { c: 20, d: 'ddd' }

원시 타입은 생각대로 b 의 값만 변경이 되었고 obj2 는 c 의 프로퍼티가 20으로 변경 되었지만 obj1 의 c 프로퍼티도 동일하게 변경된 것을 확인할 수 있다.

위의 과정은 우리가 어느정도 자바스크립트를 공부하거나 코딩을 해본 사람이라면 개념적으로 알 수 있다. Object 는 참조 타입이므로 주소가 복사되니 변수를 복사하고 프로퍼티를 변경하면 같은 곳을 바라보고 있으니 한 쪽을 변경 하더라도 동시에 변경되는 것을 확인할 수 있다.

자 그렇다면 앞서 언급한 단어인 ‘복사' 라는 단어의 의미는 잘못되었다 라고 이야기 할 수 있는데 복사 라는 것은 값을 한 쪽을 변경 하더라도 다른 한 쪽에 영향을 주면 안된다. 그렇기 때문에 ‘참조'라고 보는 것이 적절할 것이다.

위의 설명을 조금 더 구체적으로 메모리 상에서 어떻게 변화하는지 살펴보면 아래와 같다.

b 는 a 의 데이터 주소값을 복사해서 동일하게 바라보기는 했지만 값을 변경 하면서 새로운 데이터 주소 값을 할당하여 제대로 된 복사가 진행 되었다 라고 볼 수 있었던 것이다. 반면, obj2 는 obj1 의 5002 번째 주소를 할당 받았지만 Object 의 c 프로퍼티의 값을 변경할 때 obj2 입장에서의 데이터 메모리는 변화하지 않고 obj1 이 바라보는 Object 를 바라보기 때문에 프로퍼티를 변경하면 obj1과 obj2 는 동일하게 영향을 받게 되는 현상이 나타나는 것이다.

정리를 하자면, 참조형 타입은 일반적인 대입 = 으로는 값을 복사할 수 없다라는 결론을 내릴 수 있다.

만약 참조 데이터를 복사하고 싶다면 아래와 같은 문법으로 복사가 가능할 것이다.

또는 아예 { c: 20, d: ‘ddd’ } 의값을 obj2 에 할당하는 방법도 있다. 만약 위와 같은 방법 이 후 프로퍼티의 값을 변경 하면 전과 다르게 서로 다른 프로퍼티를 갖는 것을 확인할 수 있다. 이를 메모리로 표현하게 되면 아래와 같다.

살펴볼 점은 1004 번지 메모리의 obj2 가 객체 복사로 인해 새로운 주소 값을 가진 것을 확인 할 수 있다.

변수가 원시 타입에서는 기존 변수를 새로운 변수에 대입하는 것만으로 향후 값이 변경 되더라도 서로 영향을 주지 않을 수 있지만 참조 타입은 다르다. 내부의 프로퍼티의 값의 주소가 바뀌기 때문에 진정한 복사를 하려면 ES6 에서 제공하는 Spread Operator 나 Object 프로토타입의 assign 함수를 활용하여 복사하는 방법을 사용하는 것이 바람직하다.

--

--