mtseo

JavaScript 원시형(Primitive) 타입과 참조형(Reference) 타입

JavaScript의 데이터 타입은 원시형(Primitive)과 참조형(Reference) 두 가지 유형으로 분류된다.

데이터 타입은 다음과 같다:

  • 원시형 타입: String, Number, Undefined, Null, Symbol, Boolean
  • 참조형 타입: Object, Array, Function, Date

원시형 타입

let str1 = 'hello'; // 변수 str1에 문자열(원시형 타입)을 할당
let str2 = str1; // 변수 str1를 변수 str2에 복사
 
console.log(str1); // 'hello'
console.log(str2); // 'hello'
console.log(str1 === str2); // true
 
let str2 = 'world';
 
console.log(str1); // 'hello'
console.log(str2); // 'world'
console.log(str1 === str2); // false
 
let str3 = 'hello';
console.log(str1 === str3); // true

코드에서 변수 str2의 값 'hello''world'로 수정하는 거처럼 보이지만 사실 수정하는 게 아니라 'hello'는 메모리 영역에 그대로 남아 있고 'world'를 새로 만들어 메모리 영역에 저장한다. 이처럼 원시형 타입메모리 상에 한 번 만들어지면 바뀌지 않는 성질(불변성) 을 가지고 있다.

위의 코드가 전부 실행됐을 때의 메모리 영역을 보면:

메모리----
주소1001100210031004
데이터이름:str1
값:@5003
이름:str2
값:@5004
이름:str3
값:@5003
주소5001500250035004
데이터'hello''world'

처음엔 변수 str1를 변수 str2에 복사해 두 변수의 값은 @5003의 문자열 데이터 'hello'를 참조하고 있다가, 변수 str1에 문자열 데이터 'world'를 재할당하면 @5004에 world 문자열 데이터를 저장하고 변수 str2는 @5004의 문자열 데이터 'world'를 참조하게 된다.

추가로 변수 str3'hello'를 할당하면 메모리 상에 이미 'hello'가 있기에 새로 만들지 않고 @5003을 참조한다.

참조형 데이터

let obj = {
  name: 'mt',
};
 
let obj2 = obj; // 변수 obj를 변수 Obj2에 복사
 
console.log(obj); // { name: 'mt' }
console.log(obj2); // { name: 'mt' }
console.log(obj === obj2); // true
 
obj2.name = 'jake';
obj2.age = 31;
 
console.log(obj); // { name: 'jake', age: 31 }
console.log(obj2); // { name: 'jake', age: 31 }
console.log(obj === obj2); // true

코드에서 복사 된 변수 obj2의 객체 프로퍼티 값을 재할당하거나 추가하면 변수 obj도 같이 변하는 것으로 볼 수 있다. 이처럼 참조형 타입은 메모리 상에서 가변성을 띄고 있다.

메모리 영역을 살펴보면:

메모리----
주소1001100210031004
데이터이름:obj
값:@5001
이름:obj2
값:@5001
주소5001500250035004
데이터@7001~ ?'mt''jake'31
주소7001700270037004
데이터이름:name
값:@5003
이름:age
값:@5004

메모리 영역을 보면 변수 obj는 객체의 주소 값(@7001~ ?)를 참조하고 있다. 그리고 해당 객체의 프로퍼티 값들은 각각 @5003, @5004를 참조하고 있다. 다시 되짚어 보면 변수 obj를 복사한 변수 obj2의 객체 프로퍼티 값을 변경하거나 추가하면 원본 변수 obj의 객체 프로퍼티 값도 변하기 때문에 부작용에 주의해야 한다.

*더 이상 참조되지 않는 @5002의 문자열 데이터 'mt'는 추후에 자바스크립트 가비지 컬렉터에 의해 비워지고 빈 공간이 된다.

참조형 타입에 대해 조금 더 알아 보면

let obj = { name: 'mt' };
let obj2 = obj1;
 
console.log(obj === obj2); // true
 
let obj3 = { name: 'mt' };
 
console.log(obj === obj3); // false

objobj3가 같은 줄 알았지만 그렇지 않았다.

메모리----
주소1001100210031004
데이터이름:obj
값:@5001
이름:obj2
값:@5001
이름:obj3
값:@5002
주소5001500250035004
데이터@7001~ ?@8001~ ?'mt'
주소7001700270037004
데이터이름:name
값:@5003
주소8001800280038004
데이터이름:name
값:@5003

메모리 영역을 보면 obj3는 새로운 객체의 주소 값(@8001~ ?)를 참조한다. 참조형 타입은 할당될때마다 메모리 상에서 새로 만들어 진다고 보면 된다. 이는 원본 데이터를 손상 시키는 부작용을 피할 수 있는 중요한 포인트이다.

정리

자바스크립트에서 데이터의 불변성과 가변성은 메모리 상에서의 성질을 얘기하는 것이며, 원시형 타입은 불변성을 띄고, 참조형 타입은 가변성을 띈다.


참고 자료: