[JavaScript] 원시타입과 참조타입
![[JavaScript] 원시타입과 참조타입](https://firebasestorage.googleapis.com/v0/b/cruz-lab.firebasestorage.app/o/images%2Fheroes%2Fhero-1764944396141.webp?alt=media&token=dda2be2b-3b46-4aa3-9f9a-4a9b69fdbfb9)
데이터의 두 가지 타입
자바스크립트에서 변수에 담을 수 있는 데이터의 타입(자료형)은 크게 원시 타입(Primitive Type)과 참조 타입(Reference Type)으로 나눌 수 있다.

원시 타입 변수 ⇒ 데이터가 담긴 메모리에 직접 접근
참조 타입 변수 ⇒ 주소에 대한 간접적인 참조를 통해 메모리에 접근
원시 타입
변수에 원시 타입 데이터를 할당할 때 메모리 저장 방식은 이전에 변수의 선언 및 할당 포스트에서 다뤘던 내용과 같다. 메모리의 데이터 영역에 고정 크기로 원시 값을 저장하고, 해당 공간을 변수가 직접적으로 가리키는 형태를 띈다.
원시 타입은 모두 불변 값으로서 값이 변하지 않는 불변성을 갖고 있다.
💡 불변성?
불변 값과 가변 값, 그리고 상수와 변수를 구분하는 특징은 모두 '변경 가능 여부' 이다. 그렇기에 불변 값과 상수를 헷갈리기 쉽지만 둘은 메모리 중 어떤 영역의 값에 관한 것인지에서 차이가 있다.
불변 값과 가변 값을 구분짓는 것은 데이터 영역에 저장된 값의 변경 가능 여부이며, 상수와 변수를 구분짓는 것은 변수 영역에 할당된 데이터 주솟값의 변경(재할당) 가능 여부이다.
즉, 불변성이란
- 이미 할당된 변수의 값을 바꿀 수 없다는 의미 ❌
- 메모리의 데이터 영역에 저장된 값이 변경되지 않는다는 의미 ⭕️
실제 코드들을 통해 살펴보자
let name = '박중섭'
name = '개발자' + name
console.log(name) // 개발자박중섭
let num1 = 100
let num2 = 100

재할당 시 단순히 기존 값이 바뀐것처럼 보일지 몰라도 원시 타입은 불변성을 갖고 있기 때문에 데이터 영역에서 값을 변경하지 못한다 따라서 새로운 공간을 확보하여 재할당한 값을 저장하고, 변수 영역이 가리키는 값을 새로 확보한 공간의 주솟값으로 변경한다.
또한 num1과 num2는 할당된 데이터 값이 동일하므로 같은 데이터 영역을 가리키게 된다.
이를 고려하여 원시 타입의 값이 복사될 때는 어떤 일이 일어나는지 알아보자.
let num1 = 100
let num2 = num1
num1 = 1000
console.log(num2) // 100

변수 num1을 먼저 선언&할당해준 후 새로운 변수 num2에 num1을 할당(복사)해주면 num2의 데이터 값에 num1이 가리키고 있는 데이터 영역의 주솟값(@5003)이 할당된다.
그 결과 같은 데이터 영역의 주소(@5003)를 가리키게 됐을 뿐, 변수 자체의 주솟값(@1003)을 할당한 것은 아니기 때문에, 나중에 num1을 재할당하여 값을 변경시키더라도 num2는 그대로 @5003을 가리킨다.
참조 타입
자바스크립트에서 원시 타입이 아닌 모든 데이터는 참조 타입이며 객체, 배열, 그리고 함수가 대표적이다.(엄밀히 말하면 모든 참조 타입이 객체(Object)에 포함된다)
참조 타입 데이터 메모리 저장 방식
let obj1 = {
name: '박중섭',
arr: [11, 22],
}
참조 타입 데이터 또한 원시 타입 데이터와 마찬가지로 변수 영역과 데이터 영역에 나누어 값을 저장한다.
참조 타입 데이터와 원시 타입 데이터와의 차이는 '객체의 변수(프로퍼티) 영역'이 별도로 존재한다는 점이다.

-
변수 영역에 빈 공간(@1001) 확보 후, 식별자를 obj1로 지정
-
임의의 데이터 공간(@5001)에 데이터를 저장하려했으나 여러 개의 프로퍼티로 이뤄진 데이터 그룹이므로 이 그룹 내부의 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소(@7001 ~@7002)를 @5001에 저장
-
@7001, @7002에 각각 name과 arr라는 프로퍼티 이름을 지정
-
@5004에 문자열 '박중섭'을 저장 후, 이 주소를 @7001에 저장
-
obj1의 프로퍼티 중 arr는 참조 타입 데이터(배열) 이므로 따로 arr 프로퍼티 영역을 마련하고, 그 영역의 주소(@9004~@9005)를 @7002에 저장
-
@9004, @9005에 각각 배열의 인덱스 번호를 프로퍼티 이름을 지정
-
데이터 영역에 숫자형 데이터 11, 22를 각각 저장하고, 그 주소를 @9004, @9005에 저장
위의 그림을 보면 객체가 별도로 할애한 영역은 변수 영역일 뿐, '데이터 영역'은 기존의 메모리 공간을 그대로 활용하고 있다. 데이터 영역에 저장된 값은 모두 불변값이지만, 변수 영역에는 다른 값을 얼마든지 대입할 수 있다. 바로 이 부분 때문에 흔히 참조 타입 데이터는 원시 타입과 달리 가변 값이다라고 하는 것이다.
데이터의 값을 변경시키는 코드를 통해 가변성에 대해 더 알아보도록 하자
let obj1 = {
name: '박중섭',
arr: [11, 22],
}
obj1.name = 'PJS'
obj1.arr[1] = 11

식별자 변수 obj1이 가리키는 데이터 영역의 주솟값(@5001)과 데이터 영역에 저장된 객체의 변수(프로퍼티) 영역의 주솟값(@7001~, @9004~)은 일정하다. 하지만 객체의 변수(프로퍼티) 영역에 담긴 데이터 영역의 주솟값(@5006, @5004)이 바뀌었기 때문에 객체 내부의 값이 바뀌게 된다. 즉, 참조 타입 변수의 데이터 영역은 불변성을 띄지만, 객체의 변수(프로퍼티) 영역은 가변성을 띈다고 할 수 있다.
참조 타입의 복사
let person1 = {
name: '철수',
}
let person2 = person1
person2.name = '영희'
console.log(person1.name) // 영희

미리 만들어 놓은 변수 person1을 새로운 변수 person2에 할당하는 경우, 같은 데이터 영역의 주소(@5002)를 가리키게 되며, 그 결과 같은 객체의 변수 영역을 참조하게 된다. 따라서 변수 person2의 프로퍼티 값을 바꾸면 같은 주소를 참조하는 person1의 프로퍼티 값 또한 동일하게 바뀌게 된다.