모던 자바스크립트 Deep Dive - 04 변수

<SeongHun />·2022년 8월 30일
0
post-thumbnail

해당 게시물은 모던 자바스크립트 Deep Dive 책을 인용 및 참고하여 작성했음을 알려드립니다.



04 변수

변수란 무엇이고 왜 필요할까?

  • 10 + 20 을 자바스크립트 엔진이 계산(평가)하려면 숫자 리터럴과 연산자를 알고 있어야 하며, 식(표현식)을 해석(파싱)할 수 있어야 한다.
  • 사람은 계산과 기억을 모두 두뇌에서 하지만, 컴퓨터는 CPU로 연산하고 메모리를 사용해 데이터를 기억.
  • 메모리는 데이터를 저장할 수 있는 메모리 셀(memory cell)의 집합체.
    • 메모리 셀 하나의 크기는 1바이트(8비트)
    • 컴퓨터는 메모리 셀의 크기인 1바이트 단위로 데이터를 저장하거나 읽는다.
  • 각 메모리 셀은 메모리 주소(memory address)를 갖고, 메모리 주소는 메모리 위치를 나타내며 메모리 크기만큼 정수로 표현된다.
  • 10 + 20 에서 숫자 10과 20은 임의의 위치를 가진 메모리에 저장되고 CPU는 연산을 수행한다. 하지만 연산 결과인 30을 재사용 하고 싶다면 메모리 공간에 직접 접근해야될까?
    • 메모리 주소를 통해 값에 직접 접근하는 것은 매우 위험한 일이다. 때문에 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다. 만약 허용하더라도 코드가 실행될 때마다 메모리 주소는 변경되기 때문에 올바른 방법은 아니다.
  • 따라서, 프로그래밍에서 기억하고 싶은 값을 메모리에 저장하고, 재사용하기 위해 변수라는 메커니즘을 사용한다.
  • 변수는 메모리 공간을 식별하기 위해 값의 위치를 가리키는 상징적인 이름이다.
    • 때문에 변수는 컴파일러, 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환되어 실행된다. 개발자가 직접 메모리 주소에 접근하지 않고 변수를 통해 안전하게 접근할 수 있는 것이다.
  • var result = 10 + 20; 에서 연산된 결괏값 30을 메모리 공간에 저장하고, 저장된 값 30을 재사용할 수 있도록 메모리 공간에 result 라는 상징적인 이름을 붙인 것을 변수 이름(변수명)이라 한다.
  • 변수에 값을 저장하는 것은 할당, 저장된 값을 읽는 것은 참조라고 한다.
  • 변수 저장된 값의 의미를 파악할 수 있는 변수 이름은 가독성을 높인다. 개발자 의도를 명확히 나타내는 네이밍 코드를 작성하자.



식별자

  • 변수 이름을 식별자(identifier)라고도 한다. 식별자는 어떤 값을 구별하여 식별할 수 있는 고유한 이름을 뜻한다.
  • 메모리 공간에 어떤 값들이 저장되어 있는지 식별해야 되는데, 식별자는 어떤 값이 저장되어 있는 메모리 주소를 기억해야 한다.
  • var result = 10 + 20; 에서 식별자 result 는 연산된 값 30을 저장하고 있으며 메모리 주소를 가지고 있다. 따라서 식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺고, 매핑 정보도 메모리에 저장되어야 한다.
  • 즉, 식별자는 직접적인 값을 저장하고 있는게 아닌, 메모리 주소를 저장하고 있다. 식별자는 메모리 주소에 붙인 이름으로 볼 수 있다.
  • result(변수명, 식별자) -> 0x069F..(메모리 주소) -> 30(메모리)
  • 식별자는 변수에만 국한되지 않고 함수, 클래스 등에서 사용되는 이름은 모두 식별자다. 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자라고 부른다.



변수 선언

  • 변수 선언은 값을 저장하기 위해 메모리 공간을 확보하고 메모리 주소를 연결해서 저장할 수 있게 준비하는 것. 혹은 변수를 생성하는 것.
  • 변수 선언은 var, let, const 키워드를 사용.
  • var 키워드의 단점은 블록 레벨 스코프를 지원하지 않고 함수 레벨 스코프를 지원하기 때문에 의도치 않은 전역 변수 선언으로 부작용이 발생하기도 한다.
  • ES6에서 letconst를 도입한 이유는 var 키워드의 단점을 보완하기 위해서다.
    • ES6는 하위 호완성을 유지하면서 ES5의 기반 위에 새로운 기능을 추가한 것이다. 즉, ES6는 ES5의 상위 집합(superset)이다.
  • undefined는 원시 타입의 값(primitive value)이다.
  • 자바스크립트 엔진의 변수 선언
    • 선언 단계 : 변수 이름을 등록, 자바스크립트 엔진에게 변수의 존재를 알림
    • 초기화 단계 : 메모리 공간을 확보 후, 암묵적으로 undefined를 할당하여 초기화

변수 이름(식별자)은 어디에 등록될까?
변수 이름을 포함한 모든 식별자들은 실행 컨텍스트에 등록된다. 실행 컨텍스트(execution context)는 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고, 코드 실행 결과를 실제로 관리하는 영역이며, 자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.

  • var 변수 선언은 선언과 초기화 단계가 동시에 진행된다. var 변수명; 은 선언 단계를 통해 변수명을 등록하고, 초기화 단계를 통해 변수에 암묵적으로 undefined 를 할당해 초기화 한다.
  • 초기화 단계를 거치지 않으면 다른 애플리케이션이 사용했던 값이 메모리 공간에 남아있을 수 있다. 쓰레기 값을 garbage value라고 한다.



변수 선언의 실행시점, 변수 호이스팅

console.log(식별자); // undefined
var 식별자; // 변수 선언문
  • 위의 코드는 변수 선언문보다 변수를 참조하는 코드가 앞에있다. 자바스크립트는 인터프리터에 의해 한 줄씩 실행이 되어 변수 참조하는 코드가 먼저 실행되고 변수 선언문 코드가 실행된다. 때문에 선언보다 참조를 먼저 하고 있어서 참조 에러가 발생할 것 같지만 undefined 를 출력한다. 코드가 한 줄씩 실행되는 런타임이 아닌 그 이전 단계에서 변수 선언이 실행되기 때문이다.
  • 자바스크립트 엔진은 코드를 한 줄씩 실행하기 이전에 코드의 평가 과정을 거치면서 실행할 준비를 한다.
  • 자바스크립트 엔진은 평가 과정에서 모든 변수 선언문, 함수 선언문 같은 모든 선언문을 코드에서 찾아내 먼저 실행한다. 평가 과정이 끝나면 모든 선언문을 제외하고 코드를 한 줄씩 순차적으로 실행한다.
  • 변수 선언문이 코드 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 특징을 변수 호이스팅(variable hoisting)이라 한다.
  • var, let, const, function, class를 통해 선언하는 모든 식별자는 호이스팅 된다. 모든 선언문은 런타임 이전 단계인 평가 과정에서 먼저 실행되기 때문이다.



값의 할당

  • 변수 선언은 런타임 이전에 실행되지만, 값의 할당은 코드가 순차적으로 실행되는 런타임에 실행된다.
  • 변수의 선언과 값의 할당을 var num = 80; 처럼 하나의 문장으로 단축 표현해도 자바스크립트 엔진은 변수의 선언과 값의 할당을 2개의 문으로 나누어 각각 실행한다.
  • 변수에 undefined 가 할당되어 초기화되는 것은 변함 없는데, var num = 80; 에서 값 80은 undefined저장되어 있던 메모리 공간을 지우고 그 공간에 새롭게 저장(덮어씌우는)하는 것이 아니라 새로운 메모리 공간을 확보하고 그곳에 값을 할당한다. 즉, undefined 가 초기화 되어져 있는 메모리와 할당된 값 80의 메모리는 각각 존재한다.



값의 재할당

  • 재할당이란 값이 할당되어 있는 변수에 새로운 값을 다시 할당하는 것이다.
    • var num = 80; : 변수 선언, 값의 할당
      num = 90; : 값의 재할당
  • var 키워드로 선언한 변수는 undefined 로 초기화되기 때문에 엄밀히 말하자면 값을 처음 할당하는 것도 재할당이다.
  • 상수는 단 한 번만 할당할 수 있는 변수다.
  • 재할당 된 후, 이전 값들은 사용하고 있지 않으니 가비지 콜렉터에 의해 메모리에서 자동 해제되는데 언제 해제될 지는 예측할 수 없다.
  • 자바스크립트는 가비지 콜렉터를 내장하고 있는 매니지드 언어다. 가비지 콜렉터를 통해 메모리 누수를 방지한다.
    • C언어 같은 언매니지드 언어는 개발자가 명시적으로 메모리를 할당하고 해제한다. malloc(), free() 저수준 메모리 제어 기능을 제공.
    • 자바스크립트 같은 매니지드 언어는 메모리 할당, 해제, 관리 기능을 언어가 담당하고 개발자가 직접 메모리 제어하는 것을 허용하지 않는다.



식별자 네이밍 규칙

  • 가능
    • 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어, 달러 기호를 포함할 수 있다.
  • 불가능
    • 예약어(class, if, this, for, function 등)
    • 숫자로 시작
  • 좋은 변수 이름은 코드 가독성을 높인다.
  • 네이밍 컨벤션
    • 카멜 케이스(camelCase)
    • 스네이크 케이스(snake_case)
    • 파스칼 케이스(PascalCase)
    • 헝가리언 케이스(typeHungarianCase)
profile
프론트엔드 개발자..? 쉽지 않겠는걸.. 그치만 재밌는데? 좋아~ 가보자구!

0개의 댓글