해당 시리즈는 Leonardomso의 33 Concepts Every JavaScript Developer Should Know 를 보고 공부, 정리한 시리즈이며, 자세한 내용은 링크를 확인하길 바란다.
자바스크립트에서 가장 기초적이지만, 한편으로 가장 헷갈리는 개념 중 하나이다.
명확하게 이해하고 넘어갈 수 있도록 해보자!
먼저 간단하게 정의를 하고 가자면,
Value Type 은 값이 복사되어서 전달되는 데이터 타입을, Reference Type 은 값이 아닌 참조 값(메모리 주소)이 복사되어 전달되는 데이터 타입을 가리킨다.
Value Type 과 Reference Type 의 차이를 보여줄 때 많이 예시를 드는 코드들을 보자.
let a = 10
let b = a
a = 5
console.log(b)
위 코드에서 출력값이 어떻게 될까? 5 일까? 10 일까?
정답은 10
이다.
const person1 = {
name: 'park'
}
const person2 = person1
person1.name = 'choi'
console.log(person2.name)
위 코드에서의 출력값이 어떻게 될까?
정답는 'choi'
이다
이 2 가지 코드의 차이가 Value Type 과 Reference Type 의 차이를 잘 보여주는 대표적인 예시이다.
그럼 이러한 결과가 왜 나오는지 차근차근 알아가보자
++ 추가적으로 Mutable 과 Immutable 의 개념도 같이 조금 겉들여서 알아가자
먼저 Value Type 에 대해서 알아보자
Value Type 은 값이 복사되어 새로운 변수에 전달되는 데이터 타입으로,
앞 장에서 본 원시 타입을 가리킨다.
간단하게 정의를 해보자면,
할당된 메모리 공간(변수)에 실제 값이 저장되는 데이터 타입이다.
라고 할 수 있다.
앞 장에서 본 원시 타입이 Value Type 이다.
앞서 예로 들었던 코드를 한 번 살펴 보자.
let a = 10;
let b = a;
a = 5;
console.log(b); // 출력 : 10
위 코드의 출력 값은 10이다. b 는 할당 받은 a 변수의 값이 5 로 바뀌었는데 왜 그럴까?
이는 앞서 언급한 값에 의한 전달 이라는 특징 때문이다.
변수 a
, b
에 할당되어 있는 값들은 number 타입으로 모두 원시 타입(=Value Type) 이다.
그렇기에 원시 값 자체가 복사되어서 전달된다.
값 자체가 복사되어 전달된다.
라는 말이 쉽게 안 와닿을 수 있다.
아래 그림을 보면서 다시 얘기해보자.
a
라는 변수명을 가진 통해서 메모리 공간에 10
이라는 number 값을 할당하였다.다음 b
라는 변수명을 가진 메모리 공간에 a
의 값을 할당한다.
이 때! b
라는 변수명을 가진 메모리 공간은 a
와 별개이며 a
의 number 값인 10
이 그대로 복사되어 새로운 메모리 공간에 할당된다.
그렇기에 a
변수와 b
변수에 할당된 number 값인 10
으로 동일하지만, 다른 메모리 공간에 저장된 별개의 값이다.
마지막으로 a
라는 변수에 5
라는 number 값을 재할당한다.
이 때 보면, 기존에 갖고 있던 메모리 공간은 그대로 둔 채 새로운 메모리 공간에 5
라는 number 값을 갖는다.
이렇게 처리되는 핵심적인 이유는 원시 값은 변경 불가능(Immutable)한 값이기 때문이다.
헷갈리지 말아야 하는 것이 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경할 수 없다는 것은 아니다!!
변수는 메모리 공간을 가리키면 이름일 뿐이기에 값을 재할당할 수 있다. (재할당이 안되는 변수는 const
이다. )
만약 변경 가능하다면 아래와 같이 처리가 될 것이다.
Reference Type 은 참조 값이 복사되어 새로운 변수에 전달되는 데이터 타입으로,
앞 장에서 본 객체 타입을 가리킨다.
Reference Type 도 간단하게 정의를 해보자면,
할당된 메모리 공간(변수)에 참조 값이 저장되는 데이터 타입이다.
라고 할 수 있다.
대표적으로 객체, 배열, 함수 등이 있다.
앞서 예로 들었던 코드를 한 번 살펴 보자.
const person1 = {
name: 'park'
}
const person2 = person1
person1.name = 'choi'
console.log(person2.name) // 출력 : 'choi'
위 코드의 출력 값은 'choi'
다. 왜 person1 의 name 값을 변경했는데 person2 의 name 값이 변경되었을까?
이는 객체 타입의 경우 참조에 의한 전달을 하기 때문이다.
값에 의한 전달과 다르게 참조에 의한 전달은 윈시 값 자체가 아닌 참조 값을 전달한다.
참조 값이란 객체가 실제로 저장된 공간을 가리키는 메모리 주소 값을 의미한다.
즉, 값 자체가 아니라 메모리 주소 값을 전달한다는 것이다.
아래 그림을 보면서 좀 더 살펴 보자.
그림에서 볼 수 있는 것처럼 person1
이라는 변수가 갖는 메모리 공간에는 객체 값이 아닌 객체 값이 할당되어 있는 메모리 주소의 값, 참조 값이 할당되어 있다는 것을 볼 수 있다.
그럼 이어 위 코드를 그린 그림을 보자.
먼저, person1
이라는 변수을 초기화하는 과정에서 person1
의 메모리 공간에 객체의 주소가 할당된다.
다음 person2
의 메모리 공간에 person1
가 갖고 있는 참조 값이 복사되어 전달된다.
이 때, person2
에는 person1
의 참조 값이 할당되기에 동일한 참조 값을 갖는다.
다만, 각 변수의 메모리 주소가 다르기에 저장된 공간이 다르다.
위처럼 person1
의 name 값을 변경하려고 한다면, 새로운 객체를 만들어서 다른 메모리 공간에 할당하는 것이 아닌 person1
이 갖고 있는 참조 값에 있는 객체가 변경된다.
이는 앞서 새로운 메모리 주소에 값을 할당했던 Value Type 과 다르다.
그 이유는, Reference Type 은 변경이 가능(Mutable)한 타입이기 때문이다.
이처럼 객체를 할당한 변수는 재할당 없이 객체를 변경하거나 동적을 프로퍼티를 추가하거나, 삭제할 수 있다.
이로 인해, person1
과 person2
가 가리키고 있는 동일한 객체가 변경되었기 때문에 person1
의 name 값과 person2
의 name 값이 같다.
console.log(person1.name === person2.name) // true
참조 값을 전달하기에 갖는 당연하지만, 재밌는 특징이 있다.
const x = {
color: 'blue'
}
const y = {
color: 'blue'
}
console.log(x === y) // false
console.log(x.color === y.color) // true
위 코드에서 console.log(x === y)
의 출력값은 false 이다.
color
)와 프로퍼티 값(blue
)를 갖고 있는 객체를 선언했다.반면에 console.log(x.color === y.color)
의 출력값은 true 이다.
blue
라는 원시 값이기에 서로 같다.간단하게 비교를 해보면서 정리를 하자
Value Type | Reference Type | |
---|---|---|
종류 | 원시 타입 (Number, String, Boolean 등등) | 객체 타입 (객체, 배열 등) |
전달하는 값 | 값 자체 (Value) | 참조 값 (메모리 주소 ) |
변경 가능성 | X (Immutable) | O (Mutable) |
모두 값에 의한 전달, 참조에 의한 전달 이라고 하지만 사실 생각해보면 모두 전달할 때 값을 전달한다.
그 값이 실제 값 그 자체인지, 아니면 참조 값인지에 대한 차이일 뿐이다.
Value Type 은 값이 복사되어서 전달되는 데이터 타입이며, 원시 타입을 가리킨다.
Value Type은 변경 불가능한(Immutable) 값이며, 변수에 실제 값이 할당된다.
Reference Type 은 값이 아닌 참조 값(메모리 주소)이 복사되어 전달되는 데이터 타입이며, 객체 타입을 가리킨다.
Reference Type 은 변경 가능한(Mutable) 값이며, 변수에 참조 값이 할당된다.
모던 자바스크립트 Deep Dive