꾸준한 개발자

계속적인 성장을 추구하는 개발자입니다. 꾸준함을 추구합니다.

계속 쓰는 개발 노트

JAVASCRIPT/자바스크립트 이론

원시타입과 참조타입 (Primitive type & Reference type)

gold_dragon 2022. 11. 21. 23:27

자바스크립트의 데이터 타입

자바스크립트의 데이터 타입으로 7가지가 있습니다. string, number, boolean, null, undefined, symbol, object가 있으며, 데이터 타입은 원시타입과 참조타입으로 구분할 수 있습니다. string, number, boolean, null, undefined, symbol이 원시타입에 해당하며, object는 참조타입에 해당됩니다.

원시타입과 참조타입의 차이점

이 둘의 차이점을 알기 위해서는 자바스크립트에서 데이터를 어떻게 관리하고 있는지에 대한 배경지식이 있어야 합니다.

var a; // 변수 a 선언
a = 1; // 변수 a에 데이터 할당

var a = 1; // 변수 선언과 할당을 한 문장으로 표현

원시타입의 경우, 자바스크립트 엔진은 위 코드를 만났을 때 아래와 같이 데이터를 관리하게 됩니다.

 

1. 변수 a에 대한 정보를 저장할 메모리 공간을 확보합니다.

2. 확보한 공간의 식별자를 a로 지정합니다.

3. 데이터 1이 저장되어 있는 메모리 영역이 있는지 메모리 검색을 합니다. 메모리 영역이 있다면 해당 메모리 영역의 주소를 5번에서 사용하게 됩니다.

4. 3에서 해당 메모리 영역을 찾지 못했다면, 변수 a에 할당할 값인 1의 데이터를 저장할 메모리 공간을 확보하고 데이터 1을 저장합니다.

5. a라는 식별자를 검색한 후, 해당 메모리 공간에 데이터 값 1이 저장된 메모리 주소를 저장합니다.

 

자바스크립트 엔진은 자유롭게 데이터를 변환하고 효율적으로 메모리를 활용하기 위해 위와 같이 주소값을 식별자 메모리 공간에 저장을 합니다.

 

참조타입의 경우는 아래 예시와 같습니다.

var obj = {
    a: 1,
    b: 'abc'
};

1. 변수 obj에 대한 정보를 저장할 메모리 공간을 확보합니다.

2. 확보한 공간의 식별자를 obj로 지정합니다.

3. 객체 데이터를 저장할 메모리 영역을 확보합니다.

4. 객체의 프로퍼티 키를 식별자로 하는 데이터 영역을 별도로 확보합니다.

5. 각 프로퍼티의 값이 메모리 영역에 존재하는지 검색 후, 검색 결과가 없으면 데이터 값을 저장하는 메모리 영역을 확보하고, 4번에서 별도로 확보한 데이터 영역에 해당 주소값을 저장합니다.

6. 2번에서 확보한 객체 데이터를 저장할 메모리 영역에는 4번에서 확보한 주소값 범위를 저장합니다.

7. 변수 obj에 대한 정보를 저장할 메모리 영역에는 3번에서 확보한 메모리 주소를 저장합니다.

 

원시타입보다 참조타입의 경우 더 많은 메모리 공간을 필요로 합니다. 또한 이러한 메모리 관리 로직을 통해 흔히 알고 있는 원시타입은 불변성을 지니고 참조타입은 불변성을 지니고 있지 않다는 차이점 또한 설명할 수 있습니다.

원시타입은 불변성을 갖는다.

흔히 우리가 불변성을 가진다라고 판단하는 대상은 식별자 메모리 영역에 저장된 주소가 가르키는 메모리 영역을 통해 판단합니다.

var a = 1;
a = 2;

원시타입 중 number를 예시로 들면 다음과 같습니다. a에 1을 할당했다가 후에 2를 재할당했습니다. 메모리 관리 로직을 확인하면 다음과 같습니다.

1. 변수 a에 대한 정보를 저장할 메모리 공간을 확보합니다.

2. 확보한 공간의 식별자를 a로 지정합니다.

3. 메모리 영역에 값 1이 있는지 검색 후, 검색 결과가 없다면 값 1을 저장할 메모리 공간을 확보합니다.

4. a 메모리 영역에 3번에서 확보한 메모리의 주소값을 저장합니다.

5. 메모리 영역에 값 2가 있는지 검색 후, 검색 결과가 없다면 값 2를 저장할 메모리 공간을 확보합니다.

6. a 메모리 영역에 5번에서 확보한 메모리의 주소값을 저장합니다.

 

여기서 중요한 부분은 값 2를 재할당했을 때 값 1이 저장된 메모리 영역의 값이 바뀐 것이 아닌, 새로운 메모리 영역을 확보 후 그 영역에 값 2를 저장한 것입니다. 그 후 값 2가 저장된 메모리의 주소를 식별자 메모리 영역에 저장합니다. 이처럼 한 번 만든 값을 바꿀 수 없는 것이 불변성의 성질입니다.

var obj = {
    a: 1,
    b: 'abc'
}

obj.a = 3;

이와 대조적으로 참조타입의 경우는 객체 내부의 프로퍼티 키 a를 식별자로 하는 메모리 영역의 값만 바뀌게 되고, obj 메모리 영역에 저장되어 있는 주소값은 바뀌지 않습니다.

객체를 불변하게 새로 만들어보자

하나의 방법으로 새 객체를 똑같이 하드코딩해서 만드는 방법이 있습니다.

var a = {
    number: 1;
}

var b = {
    number: 1;
}

for in 반복문을 통해서 새 객체에 원래 객체의 프로퍼티들을 복사하는 함수를 만들 수도 있습니다. 또한 재귀 함수를 만들어서 새로운 객체를 만들 수 있습니다.

var copyObject = function (target) {
    var result = {};
    
    for (var prop in target) {
      result[prop] = target[prop];
    }
    
    return result;
};

스프레드 문법을 사용해서 객체를 복사할 수 있습니다.

var a = {
    number: 1
};

var b = {
    ...a
}

Object.assign 메서드를 사용해서 객체를 만들 수 있습니다.

var a = {
    number: 1
};

var b = Object.assign({}, a);

JSON 객체 메서드를 사용할 수도 있습니다. 깊은 복사를 쉽게 구현할 수 있지만, 다른 방법들에 비해 성능이 좋지 않고, 함수의 경우 undefined로 처리된다는 단점이 있습니다.

var a = {
    number: 1
}

const b = JSON.parse(JSON.stringify(a));

lodash 모듈의 cloneDeep 메서드와 같이 라이브러리를 사용하여 편리하게 객체를 새로 만들 수 있습니다.

'JAVASCRIPT > 자바스크립트 이론' 카테고리의 다른 글

호이스팅  (0) 2022.12.04
this  (0) 2022.11.22
타입이란  (0) 2021.02.16
currying이란  (0) 2021.02.05
REST API란  (2) 2021.02.03