변수란?
기존에 변수란 메모리의 위치를 기억하는 저장소의 이름, 값을 담을 수 있는 그릇이라고 막연하게만 생각해왔다.
하지만 내 생각과 조금은 달랐다.
변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다.
조금 더 자세히 알아보자
우리의 뇌는 연산과 기억을 둘다 할 수 있지만, 컴퓨터는 연산(CPU)과 기억(메모리)을 수행하는 부품이 나누어져 있다.
메모리란?
-> 데이터를 저장할 수 있는 메모리셀의 집합체이다. 메모리셀 하나의 크기는 1바이트(8bit)이다.
컴퓨터는 1바이트 단위로 데이터를 저장하거나 읽어들인다.
각각의 메모리셀은 고유의 메모리주소를 갖는다. 메모리 공간의 위치 0~메모리 크기 만큼 정수로 표현된다.
예를 들어 4GB메모리는 0~4,294,967,295(0x0000000 ~ 0xFFFFFFFF)까지 메모리 주소를 가지게 된다.
컴퓨터는 숫자, 문자, 이미지, 동영상 모두 2진수로 저장하게 된다.
10 + 20 이라는 표현식을 컴퓨터의 관점에서 생각해보자.
+ 연산자의 피연산자인 10, 20을 메모리에 저장하고, CPU가 이 값을 읽어 연산을 수행하고 30의 값을 메모리의 임의의 위치에 저장한다. 하지만 이 30이라는 값은 재사용이 불가능하다. 재사용을 위해서는 메모리 공간에 직접 접근을 해야한다.
메모리 주소 접근 (자바스크립트)
메모리 주소를 통해 직접 접근하는건 굉장히 치명적인 오류를 발생시킬 수 있기 때문에 위험하다. 만약 운영체제가 사용하고 있는 값을 변경하면 시스템을 멈추게하는 치명적 오류가 발생한다.
자바스크립트는 메모리의 주소를 직접 접근해서 제어하는 것을 허용하지 않고 있다. 또한 허용한다 해도 메모리 주소는 코드가 실행될 때마다 값이 저장되는 메모리 주소가 바뀌기 때문에 코드가 실행되기 이전에는 값이 저장된 메모리 주소를 알 방법이 없고, 알려주지도 않는다.
그러면 그 값에 접근하기 위해서는 어떻게 해야할까? 여기에서 변수가 나타난다.
프로그래밍 언어는 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어들여 재사용 하기 위해 "변수"라는 메커니즘을 제공한다.
변수 이름을 '식별자'라고도한다.
식별자란?
식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다. 자바스크립트 엔진에게 변수 선언에 의해 식별자의 존재를 알릴 수 있다.
변수 선언이란?
값을 저장하기 위한 메모리 공간을 확보하고, 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다. 자바스크립트 변수 선언은 var, let, const 키워드를 이용해서 선언할 수 있다.
키워드는 자바스크립트 엔진이 수행할 동작을 규정한 일종의 명령어이다.
var x;
위의 코드처럼 변수를 선언한 이후 아직 변수에 값은 할당하지 않았을 때
변수 선언에 의해 확보된 메모리 공간은 비어있을거라 생각할 수 있으나, 확보된 메모리 공간에는 자바스크립트 엔진에 의해 undefined라는 값이 암묵적으로 할당되어 초기화된다.
자바스크립트엔진은 변수 선언을 2단계에 거쳐서 수행한다.
1. 선언단계: 변수이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고, 암묵적으로 undefined를 할당해 초기화한다.
console.log(x); // undefined
var x;
위의 코드가 에러가 나지 않는 이유가 있다. 원래 선언하지 않은 식별자에 접근하면 Reference Error가 발생해야 한다. 하지만 왜 에러가 나지 않는 것일까?
자바스크립트는 런타임 환경에서 인터프리터가 위에서 아래로 한줄씩 해석하면서 각각의 문을 실행을 한다. 그럼 맨 위에서 x는 선언이 되지 않았으니 Reference Error가 나야하지만, 에러나 나지 않고 undefined를 출력한다. 그 이유는 런타임 전에 변수 선언이 일어난다는 것이다.
JS엔진은 소스코드를 한줄씩 실행하기에 앞서 먼저 소스코드 평가 과정을 거쳐 소스코드를 실행하기 위한 준비를 한다. 그 과정에서 변수 선언이 일어나기에 console.log(x)를 할 때 x는 이미 선언이 되어 있고 undefined로 암묵적으로 초기화 되어서 에러가 나지 않는것이다.
이러한 현상을 호이스팅이라고한다.
var,let,const,function,function*,class 키워드로 선언하는 모든 식별자는 호스팅이 된다.
값의 할당(assignment)
변수 선언( 선언단계 + 초기화 단계) + 값의 할당
var score; // 변수 선언
score = 80; // 값의 할당
var score = 80; // 변수 선언 및 값의 할당
위 두 코드는 정확히 일치하는 코드이다. 자바스크립트 엔진은 변수 선언과 동시에 값을 할당해도 변수 선언과 값의 할당을 2개의 문으로 나누어서 실행하기 때문에 정확히 일치하는 문이다.
변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 실행이 되고, 값의 할당은 소스코드가 순차적 실행이 되는 런타임에 실행이 된다.
만약에 변수에 값을 재할당하게 된다면 기존에 사용하던 메모리 공간에 있는 값을 지우고 새로운 값을 넣는 것이 아니라, 새로운 메모리 공간을 확보한 후 그 공간에 값을 저장하고 변수가 그것을 가리키게 되는 것이다.
값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 '상수'라고 한다. ES6에서는 const 키워드를 이용해서 만들 수 있다.
GA(가비지 콜렉터)
C언어와 같이 언매니지드 언어는 메모리를 개발자가 할당하고 해제할 수 있게 메모리 제어 기능을 제공한다. 이것은 개발자의 역량에 따라서 메모리 관리가 좋을 수도 있고 메모리 누수가 일어날 수 있다.
하지만 자바스크립트는 메모리 제어기능을 제공하지 않고, 어느 식별자도 참조하지 않는 메모리 공간이 있다면 GA(가비지 콜렉터)가 그 메모리를 해제해준다. 이렇게 되면 개발자의 역량에 따라서 메모리 누수, 관리의 좋음은 일어나지 않지만 어느 정도의 느려짐은 감수해야한다.
값이란?
값은 표현식(expression)이 평가되어 생성된 결과이다. (평가란, 식을 해석해서 값을 생성하거나, 참조하는 것이다)
10 + 20이 평가되면 30이라는 값이 생성된다.
모든 값은 데이터 타입을 가지며, 메모리에 2진수로 저장하게 된다. 값은 데이터 타입에 따라서 해석이 다를 수 있다.
01000001은 숫자 데이터 타입으로 해석할 시 65이지만, 문자로 해석하면 'A'가 된다.
리터럴
리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해서 값을 생성하는 표기법이다.
1 -> 숫자리터럴 1
자바스크립트 엔진은 코드가 실행되는 시점인 런타임에 리터럴을 평가해 값을 생성한다. 즉, 리터럴이란 값을 생성하기 위해 미리 약속된 표기법이라고 할 수 있다.
표현식이란
표현식은 값으로 평가될 수 있는 문(statement)를 뜻한다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존값을 참조하게 된다.
리터럴은 값으로 평가되므로 표현식이라고 할 수 있다. 50 + 50 또한 리터럴과 연산자로 이루어져 있지만 평가되어 100을 생성하므로 표현식이다.
var score = 50 + 50;
score // 100 <- 변수를 참조하면 변수 값으로 평가되므로 표현식이다.
문(statement)이란
프로그램을 구성하는 기본 단위이자 최소 실행단위를 뜻한다. 문의 집합을 프로그램이라고 하며, 문을 작성하고 순서에 맞게 나열하는 것을 프로그래밍이라고 한다. 문은 여러 토큰으로 구성된다. 토큰이란 문법적 의미이며, 문법적으로 더 이상 나눌 수 없는 코드의 기본요소(;, : 등)이다.
문은 명령문이라고도 불린다. 즉, 문은 컴퓨터에게 내리는 명령이라고 생각할 수 있다.
또한 문은 4가지로 나눌 수 있다 선언문, 할당문, 조건문, 반복문 등이 있다.
세미콜론 붙이기?
세미콜론 붙이냐 안붙이냐에 대한 논쟁은 아직도 뜨겁다.
세미콜론은 문의 종료를 나타낸다. 자바스크립트 엔진 세미콜론으로 문이 종료한 위치를 파악해서 순차적으로 하나씩 문을 실행을 한다.
그래서 문을 끝낼 때는 세미콜론을 붙여야한다. 하지만 0개 이상의 문을 중괄호로 묶은 코드블록({...}) 뒤에는 붙이지 않는다.
코드블록 자체가 자체종결성을 가지기 때문이다.
세미콜론은 생략이 가능하다. 왜냐하면 자바스크립트 엔진이 소스코드의 문의 끝이라고 예측되는 시점에 세미콜론을 자동으로 붙여주는 기능이 있기 때문이다. 하지만, 개발자의 의도와 다르게 세미콜론이 들어갈 수 있으니 조심해야한다.
'모던 자바스크립트 Deep Dive' 카테고리의 다른 글
모던 자바스크립트 Deep Dive 3일차 (데이터 타입, 연산자, 제어문) (0) | 2022.07.02 |
---|---|
모던 자바스크립트 Depp Dive 공부 1일차 (0) | 2022.06.27 |