JS 기본형 데이터 타입

코곰·2022년 10월 30일
1

#이 내용은 코어자바스크립트(by. 정재남)의 강의내용과 책을 정리한 내용입니다.

프로그래밍 언어를 공부하기 위해 책을 구매해 공부해본 사람이라면 대부분 초반에 data type에 대한 설명이 되어있을 것이다. 대부분은 단순한 data type에 대한 설명 예를 들어, int가 표현하는 범위나 이를 선언하고 변수에 값을 할당하는 예제 코드를 보여주는 것이 대부분이다.

하지만 이는 사용자의 입장만 보여준 부분이다. 컴퓨터는 우리가 변수를 선언하고 해당 변수에 값을 넣는 과정은 모두 이진법화되어 메모리를 할당하고 값을 저장하는 과정을 거친다.

이는 매우 당연한 이야기이고 누구나 할 수 있는 이야기지만 각 언어별로 어떻게 메모리에 접근해 저장하는지에 대해 아는 개발자는 몇 없을 것이다. 이를 몰라도 개발하는 것에 전혀 문제가 없고 컴퓨터가 자동으로 해주기 때문이다.

하지만 지금 상황에서는 이를 몰라도 되지만 추후 방대한 양의 데이터를 다루거나 혹은 최적화가 필요한 작업을 나중에 하기 위해서는 꼭 알아야하는 내용이다.(사실 이 책을 구매할 때 너무 얇은데 왠만한 프로그래밍 서적과 값이 비슷해 반신반의했지만 첫 장을 공부한 이후에는 생각이 바뀌었다.)


  1. ES6 기준 data type에는 기본형과 참조형 크게 2종류가 있다.

    • 기본형(primitive) : Number, String, Boolean, Null, Undefined, Symbol
    • 참조형(reference) : Object(Array, Function, Date, RegExp, Map/WeakMap, Set/WeakSet)
    • 두 type의 가장 큰 차이점은 변수에 할당이나 연산시
      기본형은 주솟값을 바로 복제하는 반면
      참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제
      한다는 점이 다르다.

  2. JS는 변수에 형변환에 자유롭다.

    대부분의 변수를 선언할 때에는 var을 사용한다.

    var a = 10; // JS
    int a = 10; // C

    위 두 코드는 각 언어별로 같은 값을 의미한다. 하지만 C에 선언된 변수 'a'는 무조건 int 값만 넣을 수 있다.
    반면에 JS에 선언된 변수 'a'는 나중에 'abc'라는 값을 대입해도 오류를 발생하지 않는다.

    이러한 이유는 JS는 숫자형 데이터에 대해 8byte의 공간을 확보하기 때문이다. 반면에 c++은 숫자형 데이터라고 해도 int, float 등 선언을 통해 각기 다른 메모리의 공간을 확보하기 때문에 형변환이 자유롭지 않다.

  3. 그렇다면 변수와 기본형 datatype의 데이터는 어떻게 메모리에 저장될까?

    var a = 10;

    실제 메모리 구조는 더 복잡하지만 이를 개략적으로 다음과 같이 표현해 설명하겠다.

    주소...1002100310041005...
    데이터

    주소...5002500350045005...
    데이터

    위쪽 1002~1005번대는 변수가 저장되는 변수영역, 아래쪽 5002~5005는 데이터가 저장되는 데이터 영역이라고 하겠다.

    이는 책과 강의에서 사용된 개념으로 정식 명칭은 아니지만 이해를 돕기 위해 명명한 것이다.

    위 코드에서는 변수 선언과 데이터 할당이 동시에 한 줄에 표현되어 있지만 실제로는 다음과 같다.

    1. 먼저 변수 영역의 메모리에 비어있는 공간 하나를 확보한다.(@1002)
    2. 확보한 공간의 식별자를 'a'로 지정한다.

    주소...1002100310041005...
    데이터식별자 : a
    값 :

    주소...5002500350045005...
    데이터

    3. 데이터 영역의 비어있는 메모리(@5002)에 데이터를 저장한다.

    주소...1002100310041005...
    데이터식별자 : a
    값 :

    주소...5002500350045005...
    데이터10

    4. 변수 영역에서 a라는 식별자를 검색한다.(@1002)
    5. 앞서 저장한 문자열의 주소(@5002)를 @1002의 공간에 대입한다.

    주소...1002100310041005...
    데이터식별자 : a
    값 : @5002

    주소...5002500350045005...
    데이터10

  4. @1002의 값에 그냥 10을 저장하면 되는게 아닌가?

    물론 가능하다. 하지만 이는 데이터 변환을 자유롭게 할 수 있게 함 + 메모리를 더 효율적으로 관리가 가능하다는 장점이 있다.

    예를 들어 @1002 공간의 값에 10을 저장했다고 해보자. 만일 이 값을 "안녕하세요. 반갑습니다."인 문자형 데이터로 형변환을 하기 위해서는 @1002가 확보한 8byte보다 많은 공간을 필요로 한다.(한글은 글자당 2byte가 필요하기 때문이다)

    즉, 만일 이런 사태가 발생되게 된다면 @1002 공간을 늘리기 위해 @1003~의 공간을 조정해야한다. 하지만 만일 뒤에 데이터가 무수히 많다면 연산이 굉장히 많아진다.

    한 경우에서는 이것이 더 효율적일지 모르지만 데이터가 많아질수록 매우 비효율적이기 때문에 변수와 데이터를 별도의 공간에 나누어 저장하는 것이 최적이다.

  5. 그럼 할당한 값도 만일 값을 변경하면 위와 같이 비효율적인 사태가 발생되는 것은 아닐까?

    결론만 이야기하면 맞다.
    그래서 데이터가 저장된 곳(@5002)의 값을 변경하지 않고 새로운 곳에 값을 저장한다.

    만약 아까 선언한 a의 값을 변경한다고 해보자.

    var a = 10;
    a = 'abc'

    1번째 줄부터 보면 아까와 같이 메모리에는 다음과 같이 저장된다.

    주소...1002100310041005...
    데이터식별자 : a
    값 : @5002

    주소...5002500350045005...
    데이터10

    2번째 줄이 실행되면 다음과 같은 절차에 따라 a에 대입된 값이 변경된다.
    1. 먼저 데이터 영역의 비어있는 메모리(@5003)에 데이터를 저장한다.
    주소...1002100310041005...
    데이터식별자 : a
    값 : @5002

    주소...5002500350045005...
    데이터10abc
    2. 변수 영역 중 식별자가 'a'인 것을 찾는다.
    3. 앞서 저장한 문자열의 주소(@5003)을 @1002에 대입한다.
    
    주소...1002100310041005...
    데이터식별자 : a
    값 : @5003

    주소...5002500350045005...
    데이터10abc
  6. 그럼 @5002에 저장된 데이터는 어떻게 되는가?

    만약 @5002를 참조하는 것이 변경되기 전의 변수 'a'가 유일했다면 어떠한 곳에서도 @5002를 참조하지 않는다. 즉 참조카운트가 0이 된다. 이러한 데이터는 Garbage Collecting의 대상이 되어 언젠가 조용히 사라지게 된다.

#혹시나 오류나 틀린 설명이 있다면 언제든지 말씀해주시면 감사하겠습니다!

profile
입니다.

1개의 댓글

comment-user-thumbnail
2022년 10월 30일

잘보고 갑니당 ㅎㅎ

답글 달기