원시 자료형과 참조 자료형

유슬기·2023년 1월 2일
0

프론트엔드

목록 보기
15/64
post-thumbnail

원시 자료형(primitive data type)

  • JavaScript에서 원시 타입의 데이터(원시 자료형)는 객체가 아니면서 메소드를 가지지 않는
    string, number, bigint, boolean, undefined, symbol, (null)이 있음
  • 변수에 값을 저장할 때 하나의 데이터만 담을 수 있으며, 원시 자료형이 할당될 때에는 변수에 값(value) 자체를 저장함
    • 원시 자료형은 고정된 크기의 저장소(stack)에 변수명과 데이터가 함께 담긴다

참조 자료형(reference data type)

  • JavaScript에서 원시 자료형이 아닌 모든 것은 참조 자료형.
    배열([])과 객체({}), 함수(function(){})가 대표적
  • 변수에는 하나의 데이터만 담을 수 있으며, 값을 저장하는 대신 데이터가 담긴 저장소의 주소(reference)를 저장함
    • 참조 자료형은 기존에 고정된 크기의 저장소(stack)가 아니라, 동적으로 크기가 변하는 저장소(heap)를 사용할 수 있음
    • heap에 데이터의 내용을 보관, stackheap의 주소를 저장
    • 실제 데이터는 heap에서 별도로 관리되며, 데이터를 호출할 때 stack에 저장되어 있는 주소를 참조하여 heap에서 데이터를 찾아 반환함

자바스크립트의 메모리 구조

스택, 힙이라는 말이 계속 나오는데, 정확히 어떤 걸 의미하는지, 무슨 차이가 있는지 궁금해져 따로 찾아보았다.

자바스크립트 엔진은 Code Area, Memory Heap, Call Stack으로 구성되어 있다

  1. Code Area: 실행할 JS 코드가 저장되는 영역

  2. Call Stack: 원시 타입 데이터가 저장되는 메모리 공간

    stack-memory-explained.png

    콜 스택은 JavaScript가 정적 데이터를 저장하는 데 사용하는 데이터 구조이다. 

    • 정적 데이터: Static Data
      • 메모리에 데이터를 올려놓은 상태(로드)에서 필요할 때마다 데이터를 호출하여 사용하는 데이터
      • 최소의 변화를 요구하는 고정된 데이터
      • 엔진이 컴파일 타임에 크기를 알고 있는 데이터

    여기에는 원시 타입의 데이터 ( strings , numbers , booleans , undefined 및 null ) 및 참조(reference)가 포함된다.

    • 참조: 객체, 배열의 주소값 등

    자바스크립트 엔진이 데이터의 크기가 변경되지 않는다는 것을 알고 있으므로 각 값에 대해 고정된 양의 메모리를 할당한다.

  3. Memory Heap: 참조 타입 데이터가 저장되는 메모리 공간

    stack-heap-pointers.png

    사용자 프로그래머가 직접 할당/해제 하는 메모리 영역

    메모리 힙에는 객체, 배열, 함수 와 같이 크기가 동적으로 변할 수 있는 참조타입 데이터가 저장된다.

참조 타입 데이터는 콜 스택과 메모리 힙에서 어떻게 관리되는가?

참조 타입 데이터를 저장하는 경우 Call StackMemory Heap의 주소를 저장, Memory Heap에 데이터의 내용을 보관한다.

실제 데이터는 Memory Heap에서 별도로 관리되며, 데이터를 호출할 때 Call Stack에 저장되어 있는 주소를 참조하여 Memory Heap에서 데이터를 찾아 반환한다.

위 이미지의 변수 a는 원시 자료형이므로 콜스택에 저장될 때 값이 저장됨을 볼 수 있다.
나머지 변수 b, c, d는 각각 배열, 객체, 함수와 같은 참조 자료형이므로 콜스택에는 주소가 저장된다.

예시로 이해하는 원시/참조 자료형

  • 원시 자료형
    let x = 2;
    let y = x;
    // 변수 x를 변수 y에 할당할 때, 변수 x의 값이 원시자료형이므로 x의 값인 2를 y에 복사하여 할당
    console.log(y); // 2
    
    y = 3; // 변수 y에 3을 재할당되어도 x의 값은 그대로 2임
    console.log(x); // 2
    console.log(y); // 3
  • 참조 자료형
    let x = [1, 2, 3, 4];
    let y = x;
    // 변수 x를 변수 y에 할당할 때, 변수 x의 값이 참조자료형이므로 x의 값이 아닌 주소를 y에 복사하여 할당 (같은 주소를 바라보고 있는 상태)
    console.log(y); // [1, 2, 3, 4]
    console.log(x === y) // true
    y.push(5); 
    // 변수 y 배열에 push 메소드로 마지막 인덱스에 5를 추가하면 같은 주소를 바라보고 있는 x 또한 함께 변경 됨
    console.log(x); // [1, 2, 3, 4, 5]
    console.log(y); // [1, 2, 3, 4, 5]
    let x = { foo: 3 };
    let y = x;
    // 변수 x를 변수 y에 할당할 때, 변수 x의 값이 참조자료형이므로 x의 값이 아닌 주소를 y에 복사하여 할당 (같은 주소를 바라보고 있는 상태)
    console.log(y); // { foo : 3}
    console.log(x === y); // true
    y.foo = 2;
    // 변수 y 객체의 foo 속성 value에 2를 할당하면 같은 주소를 바라보고 있는 x의 foo 속성 또한 함께 변경 됨
    console.log(x); // { foo : 2}
    console.log(y); // { foo : 2}
  • 함수
    let score = 80;
    
    function doStuff(value) {
      value = 90;
      return value;
    }
    
    doStuff(score); // score의 값을 인자로 전달하여 doStuff 함수 실행
    
    // 변수 score의 값은 원시 자료형이므로 값 자체를 복사하여 전달함 (함수 실행 결과와 관련없이 초기 값 80이 유지)
    console.log(score); // 80
    
    // 함수 실행 시 반환되는 결과 값은 value의 값인 90
    console.log(doStuff(score)); // 90
    console.log(value); // 90
  • 동치 연산자
    // string 타입과 number 타입은 원시 자료형
    // 원시 자료형의 ===(동치 연산자)는 값이 같은지 확인
    console.log('codestates' === 'codestates'); // true
    console.log(3.14 === 3.14); // true
    // array 타입과 object 타입은 참조 자료형
    // 참조 자료형의 ===(동치 연산자)는 참조된 주소값이 같은지 확인(값이 같아도 주소가 다르면 false)
    console.log([1,2,3] === [1,2,3]); // false
    console.log({ foo: 'bar' } === { foo: 'bar' }); // false

참조
https://felixgerschau.com/javascript-memory-management/
https://curryyou.tistory.com/276

profile
아무것도 모르는 코린이

0개의 댓글