티스토리 뷰

728x90
반응형

 

22.06.07 일부 내용 수정

 

자바스크립트 변수 선언과 할당 동작 과정 이해

현재 자바스크립트를 배우고 있는데 느끼는 점이 굉장히 많다. 당연하다고 생각하던 것이 당연한 것이 아니었던 것이다.  프로그래밍에 입문하면서 C, C++을 배웠었는데, 동작의 결과에 대해서는 당연하게 생각하고 왜 그런 동작을 하는지에 대한 고민을 해본 적이 별로 없었다. 또한 오류가 나도 해결하는 게 중요했지, 왜 오류가 나는지 고민을 해본 적이 별로 없었다.

이번에 자바스크립트를 배우면서 동작 원리의 정확한 이해라는 방향성을 가지고 공부를 하면서 기본이 정말 중요하다는 생각을 하게 됐다. 과연 내가 혼자 공부를 했다면, 이런 방향성을 생각하면서 공부할 수 있었을까? 여기에서 정확한 이해라는 방향성이란 기본에 충실하는 것을 의미한다. 어느 분야든 올바른 방향성을 가질 수 있게 해주는 스승을 만나는 것은 참 중요한 것 같다. 당연하다고 생각하고 넘어갔던 자바스크립트에서 변수 선언과 할당 동작 과정에 대해 정리해보려 한다.

 

1. C와 JS에서의 변수 선언과 할당 비교

먼저 C에서는 변수 선언과 할당 과정이 다음과 같다. int형을 정해준 변수 선언 방식(정적 타입)

  • c에서의 변수 선언과 할당
int a;
a = 1;
printf("%d", a); // 1

 

하지만 자바스크립트에선 다음과 같다. 데이터 타입에 관계없이 var를 활용해 변수를 선언한다.(동적 타입)

  • JS에서의 변수 선언과 할당
var a;
a = 1;
console.log(a); // 1

 

위와 같은 방식들을 해당 언어들만의 특징 정도로만 생각했고, 당연하게 받아들여야 하는 문법 정도로 생각했다. '자바스크립트에서 알아서 처리해주나 보다' 정도로만 이해하고 넘어갔다. 하지만 내 생각보다 복잡한 동작이 있었다. 이러한 동작을 이해하니 호이스팅이라는 안티 패턴도 자연스럽게 이해할 수 있었다. 

 

2. 용어에 대한 확실한 정의

당연하게 생각하는 것들이란 무엇일까? 혹시 "변수란 무엇인가?"라는 질문을 받았을 때, 명확하게 설명이 가능한지 모르겠다. 나는 변수에 대한 질문을 받았을 때, 머릿속으로는 떠오르지만 말로 나오지 않았다. 그리고 '변수가 변수지....'라고 생각을 했다. 하지만 어떤 개념을 이해한다는 것은 바로 용어를 정확히 이해하고 설명할 수 있어야 제대로 아는 것이라고 배우고 있는데, 굉장히 동의하는 부분이고 중요한 것 같다. 결국 나는 변수에 대해서도 제대로 알지 못했던 것이다.

변수란 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다. 식별자라고도 부른다.

"식과 문을 구별할 수 있는가?"라는 비슷한 질문도 있다. 문은 프로그램의 최소 실행 단위이다. 표현식은 값으로 평가될 수 있는 문이다. 따라서 식은 문이다. 하지만 표현식인 문일 수도 있고, 표현식이 아닌 문일 수도 있다. 따라서 문이 값으로 평가가 될 수 있다면 표현식인 문이다. 처음엔 이런 용어들을 대수롭지 않게 생각했다. 대충 식과 문을 이해하고 넘어가서 개념이 많이 흔들리고 헷갈리는 것을 경험했다. 용어들의 정의를 확실히 알고 이해해야 더욱 깊은 내용들을 이해할 수 있었다.

2 + 3 // 표현식 리터럴이 5로 평가가 된다.
var x; // 선언문은 표현식이 아니다. 값으로 평가가 될 수 없기 때문에
x = 10; // 할당문은 표현식인 문이다.

 

위에서 변수란 하나의 을 저장하기 위한 메모리 공간 자체라 했다. 표현식은 으로 평가가 가능하다. 따라서 표현식은 변수에 할당할 수가 있다. 하지만 표현식이 아닌 문은 변수에 저장할 수가 없다. 이런 용어의 확실한 정의를 바탕으로 자바스크립트 변수 선언과 할당 과정을 정리해보려 한다.

 

3. 자바스크립트 변수 선언과 할당

다음과 같이 선언을 했을 때, 자바스크립트에서는 어떻게 동작이 일어날까? 먼저, 자바스크립트에서는 런타임 이전에 변수 선언문을 실행 컨텍스트에 객체로 등록한다. 실행 컨텍스트라는 개념을 정확하게 이해하는데 굉장히 오랜 시간이 걸렸다. 실행컨텍스트란 자바스크립트 동작원리의 핵심 개념으로 식별자를 등록하고 식별자를 관리하는 스코프와 코드 실행 순서 관리를 구현한 자바스크립트의 내부 메커니즘이다. (Deep Dive 23장- 실행컨텍스트)

실행컨텍스트는 생략하고 변수 선언의 과정만을 살펴보면 다음과 같다.

var age;
age = 30;

 

age라는 변수를 선언하게 되면, age라는 메모리 공간을 확보하고 undefined로 초기화를 하게 된다. 그러면 age라는 변수는 undefined 값을 가진 메모리 공간을 가리킨다. 아래 그림과 같다.

변수 선언

undefined 타입의 메모리 크기?

undefined에 대한 메모리 공간의 크기는 얼마나 될까? 브라우저 엔진을 직접 까 보지 않는 이상 알 수 없다. ECMAScript에 이에 대한 명세가 없기 때문에, 브라우저 엔진을 만드는 개발사의 자율이다. 따라서 브라우저 엔진마다 다를 수 있다고 한다.

변수의 데이터 타입별로 memory size를 반환해주는 함수를 zensh의 github에서 찾을 수 있었다. 해당 글의 함수를 크롬 개발자 도구의 console에 입력해주고 직접 변수에 데이터 타입별로 값을 할당해주면서, 데이터 타입의 size를 확인해볼 수 있다. 하지만 값이 null과 undefined인 경우에는 제공을 하고 있지 않다.

 

이후 age=30의 할당 문을 실행하면, 자바스크립트에서는 30이라는 을 할당하기 위해 새로운 메모리 공간을 확보하고 30이라는 값을 저장해준 뒤, age가 해당 메모리 공간을 가리키게 된다. 

값 할당

var age = 30;

// 아래 동작과 같다
var age;
age = 30;

위와 같이 단축해서 써줘도 똑같은 동작이 일어나게 된다. 당시에는 메모리가 상당히 중요했기 때문에, 더 효율적인 방식으로 메모리를 관리할 수 있는 방식으로 만들어지게 됐다고 한다. 자바스크립트에서는 값의 변경은 재할당을 통해서만 이루어진다. 따라서 자바스크립트에서는 값을 재할당할 때, 새로운 메모리 공간을 확보하고 해당 메모리에 값을 할당해주게 된다. 또한 값을 할당하는 과정에서 얼마만큼의 메모리 공간을 확보할 것인지에 대한 데이터 타입에 대한 내용의 공부가 필요하다. 원시 타입과 객체에 대한 이해도 필요하다.

C는 메모리 할당과 해제를 직접 관리해줘야 하고, 자바스크립트는 자바스크립트 엔진이 메모리 관리를 해주게 된다. 이를 가비지 콜렉터라고 한다. 가비지 콜렉터란 메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리를 해제하는 기능이다. 변수 선언과 할당에서부터 공부할 내용이 벌써 3가지나 생겼다. 호이스팅에 대한 부분만 짚고 넘어가려 한다.

  1. 호이스팅 (안티 패턴)
  2. 데이터 타입 (값을 할당 시 얼마만큼의 메모리 공간을 확보할 것인가)
  3. 가비지 콜렉터 (참조되지 않는 메모리 정리)

 

4. 변수 호이스팅

변수 호이스팅이란 변수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징이다. 이러한 현상은 자바스크립트의 태생적 특징이라고 한다. 자바스크립트 창시자인 브랜던 아이크 씨의 생각이 많이 들어갔는데, 비개발자도 편리하게 사용할 수 있게, Error를 내지 않는 방향으로 고민을 하다 보니, 런타임 이전에 선언된 변수들을 실행컨텍스트에 미리 등록해 아래와 같은 코드도 Error를 내지 않게 만들었다고 한다.

console.log(age); // undefined

var age;
age = 30;

console.log(age); // 30

일반적으로 첫 번째 줄의 console문은 age가 선언이 되지 않았기 때문에 참조 에러가 발생해야 맞다. 하지만 undefined가 출력이 된다. 자바스크립트에서는 런타임 이전에 변수 선언문들이 미리 실행이 된다. 따라서 age라는 변수가 선언이 되고, undefined로 초기화가 되는 과정이 런타임 이전에 일어나게 된다. 따라서 런타임이 진행되면서 첫 번째 줄의 console문에서 초기화된 undefined가 출력이 되는 것이다. 이런 현상을 변수 호이스팅이라고 한다. (함수 호이스팅도 존재) 이전에는 최상단으로 끌어올리는 효과라고만 암기를 했지만, 배경과 이유를 배우고 나니 호이스팅이라는 현상의 이해가 쉬웠다.

변수가 선언이 되지 않았는 데 사용하면 안 되는 것은 어느 언어나 명확한 문제이지만, 자바스크립트의 태생적 특징(브랜던 아이크 씨의 생각들) 때문에 오류를 발생시키지 않는 것뿐이라고 한다. 따라서 이러한 호이스팅 현상은 피해야 하는 안티 패턴이지만, 자바스크립트가 오류를 발생시키지 않는다고 이해하면 될 것 같다.

 

 

5. 결론

자바스크립트에서 기본적인 동작 원리를 제대로 이해하면 호이스팅과 같은 현상이 왜 일어나는지 자연스럽게 이해를 할 수 있었다. 어떻게 보면 너무 당연한 부분이라 생각할 수 있지만, 이러한 동작을 자세하게 설명하는 것은 굉장히 어려웠다.  그 이유는 용어에 대한 정의가 명확하지 않았기 때문이다. 용어를 정확하게 이해하고 이를 바탕으로 실행컨텍스트, 클로저의 내용으로 개념을 확장해야만 어려운 개념도 풀어서 이해할 수 있다는 것을 깨달았다.

 

혹시 틀리거나 잘못된 내용이 있다면 댓글로 알려주세요. :)

 

 

📕 Reference: 

모던 자바스크립트 Deep Dive 4장 변수

https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management

https://poiemaweb.com/js-data-type-variable

 

728x90
반응형
댓글