Study/JavaScript Deep하게 공부하기

[JS Deep 하게 공부하기] - 변수란?

반응형
SMALL

변수의 의미와 변수 선언

자바스크립트 내의 변수란, 값을 저장해놓은 메모리를 접근할 수 있는 식별자라고 할 수 있습니다.

 

즉, 값을 저장해놓은 메모리를 접근할 수 있게 해주는 별명같은 것이라고 이해하면 쉽게 이해할 수 있습니다.

 

변수는 모든 프로그래밍 언어에서 빠져서는 안되는 중요한 역할을 합니다, 변수가 없으면 값을 기억할 수도 없고 값을 직접적으로 사용할 수 도 없어집니다.

 

변수는 JavaScript 내에서 아래와 같이 사용할 수 있습니다.

var 변수 이름 = 값;

변수 이름을 지정하고 지정한 메모리 안에 값을 할당하는 것입니다, 위의 변수는 선언과 정의를 동시에 수행한 것입니다. 

 

위에서는 저렇게 사용해서 변수의 선언과 정의를 동시에 수행할 수 있지만 자바스크립트 엔진 내에서는 아래와 같이 선언과 정의를 구분짓습니다.

var 변수이름;

변수이름 = 값;

여기서 선언이란 변수가 새롭게 선언 되었다는 것을 의미(변수의 존재를 알림)하고, 정의란 선언된 변수 안에 값을 할당함으로써 변수의 사용을 정의(변수가 직접적으로 정의되어 사용한다고 알림)했다고 할 수 있습니다.

 

아래의 변수 선언을 예시로 들어보겠습니다. 

var a = 1;

변수 이름을 a라고 지정하고 a 변수에 1을 할당(변수에 값을 대입)한 것입니다.

변수의 장점과 원리

var a = 1;

해당 코드를 실행하게 되면 메모리에는 다음과 같이 지정됩니다.

 1이라는 값은 특정 메모리 주소에 저장하고 해당 메모리 주소를 a라는 식별자로 지정한 것 입니다.

 

여기서 변수가 무슨 역할을 하는지 알 수 있습니다, 변수 a는 직접적으로 1이라는 값을 가지고 있는것이 아니라 1을 저장한 "메모리 주소"를 기억하고 있습니다.

 

즉, 위의 사진에서는 a는 1이 아닌 a는 0x000123이라는 메모리 주소가 저장되어 있습니다, 그러므로 위의 코드가 실행되면 메모리에서 0x000123이라는 위치에 가서 1이라는 값을 가져오게 됩니다.

 

a라는 이름은 별명과 같은 역할입니다 변수의 이름을 일일히 메모리 주소로 하게 된다면 0x000123, 0x000124, 0x000125 등과 같이 사용해야 합니다, 또한 메모리의 위치는 파일이 실행될때마다 계속해서 다르게 저장됨으로 계속해서 변수 이름을 바꿔야 할 것입니다.

 

a라고 메모리 주소를 대체해서 이름을 지정하게 되면 파일이 실행될때마다 a라는 변수에는 1이 저장된 메모리의 위치가 계속해서 바뀌기 때문에 계속 접근할 수 있고, 보안면에서 메모리 주소가 노출되지 않는다는 점도 장점입니다. (자바스크립트에서는 개발자의 직접적인 메모리 제어, 접근, 사용 등을 허용하지 않는 메니지드 언어입니다.)

메니지드 언어 (Managed Langage) : 대부분의 동적 언어는 메니지드 언어입니다, 메니지드 언어란 개발자가 언어 내에서 직접적인 메모리의 접근, 제어, 사용등을 허용하지 않은 언어를 말합니다, 대표적으로 JavaScript, Python, PHP 등이 있습니다.

언메니지드 언어 (Unmanaged Langage) : 정적 언어는 대부분 언메지니드 언어입니다, 해당되는 언어들은 메니지드 언어와 반대입니다, 개발자가 프로그램 내에서 직접적인 메모리 접근, 제어, 사용, 관리 등을 허용합니다, 대표적으로 C, C++, C#, Go 등이 있습니다.

var 변수 호이스팅

호이스팅이란 런타임 과정 전에 선언문이 코드의 최상단으로 끌어올려지는 것을 뜻합니다.

console.log(a);

var a = 10;

인터프리터 언어는 일반적으로 코드가 위에서부터 1줄씩 아래로 내려가면서 실행한다는 특징이 존재합니다, 그렇다면 console.log(a)를 한 후 a라는 변수를 선언했는데(정의포함) 일반적이라면 "Not Found Error"가 발생한다고 생각합니다.

 

하지만 해당 코드는 에러가 발생하지 않습니다.

 

해당 코드를 실행시키게 되면 아래와 같은 결과를 얻을 수 있습니다.

undefined

왜 오류가 발생하지 않고 "undefined" (정의되지 않음)이 출력되는 것일까요?

 

이는 변수 호이스팅에 이유가 존재합니다, var 변수는 호이스팅 됩니다.

 

호이스팅이란 위에서 설명하였듯이 프로그램이 런타임 전에 코드 최상단으로 끌어올려지는 것을 뜻한다고 했습니다.

 

이는 자바스크립트의 특징인데, 자바스크립트 엔진에서는 프로그램이 1줄씩 실행되기 이전(런타임 이전)에 모든 선언문들을 탐색하여 코드의 최상단 으로 끌어올린 후 코드를 1줄씩 실행합니다, 이를 변수 호이스팅이라고 합니다.

 

즉, 위의 코드를 자바스크립트 엔진의 입장으로 해석해보면 아래와 같습니다.

var a;

console.log(a);

a = 10;

var a = 10이 가장 최상단으로 끌어올려지면 a가 10이 나와야하는것이 아닌지 의문점을 가질 수 있는데, 호이스팅은 "선언"문만 코드의 최상단으로 끌어올려집니다.

 

그러므로, 정의의 과정인 a = 10;은 최상단으로 끌어올려지는 것이 아닌 1줄씩 실행될때 순차적으로 실행되는 것입니다.

 

undefined가 출력된 이유는 변수가 처음으로 선언되게 되면 초기값으로 undefined가 암묵적으로 할당되어 있기 때문입니다. 

 

이는 프로그램에서 쓰레기 값의 출력을 방지하기 위한 조치입니다.

쓰레기 값 (Trash Value) : 쓰레기 값이란 이전 프로그램에서 사용되고 남은 값이 제거되지 않고 남아있어서 생기는 현상입니다, C, C++ 등의 정적 언어에서 주로 나타나는데, 프로그램은 실행될때마다 메모리의 주소가 모두 바뀝니다.

즉, 프로그램이 실행되고 메모리의 주소가 바뀔때, 바뀐 메모리의 주소 안에 전 프로그램에서 쓰던 값이 남아있을 수 있습니다.

이와 같은 현상이 발생하는 이유는 전 프로그램에서 메모리를 사용하고 제거해주지 않아서 발생하는 일입니다, 이와 같이 이전 프로그램에서 사용되고 남은 값을 쓰레기 값 이라고 말합니다.

자바스크립트에서는 메모리에서 쓰레기 값이 출력되는 것을 방지하기 위해 변수가 선언되면 암묵적으로 undefined라는 자바스크립트의 고유 원시타입으로 값을 초기화 합니다.

 

즉, 위의 코드를 실행하게 되면 a 변수가 호이스팅 되고 선언과 동시에 undefined 로 초기화 되었기 때문에 a를 출력하면 undefined가 출력되게 되는 것 입니다.

변수의 재할당

상수(변수가 선언 후 정의되고 값 변경될 수 없는 변수)가 아닌 변수는 재할당이 가능합니다.

var a = 10;

console.log(a); // 10

a = 20;

console.log(a); // 20

위와 같이 var 키워드로 선언된 변수의 경우는 재할당이 가능합니다.

 

재할당이 되면 같은 메모리 주소에 기존의 10이라는 값을 지우고 20이라는 값이 새롭게 변경되는 원리가 아닙니다.

 

재할당을 수행할 경우 새로운 메모리 주소에 20이라는 값을 할당하고 a 식별자의 메모리 주소를 20이 저장된 메모리 주소로 참조를 변경하는 것 입니다.

위와 같이 기존 10이라는 값을 가지고 있는 메모리 주소에서 20을 가지고 있는 새로운 메모리 공간을 만든뒤 a 식별자의 주소를 해당 메모리 주소로 참조를 변경합니다.

 

사실이게 끝이 아니라 과정 1개가 생략되었습니다.

 

호이스팅에서 설명하였듯이 변수는 선언될때 암묵적으로 undefined라는 값이 할당됩니다, 여기서 10이라는 메모리 주소로 참조가 변경된거고 20이라는 또 새로운 주소로 참조가 변경된 것 입니다.

정상적인 메모리 재할당의 원리는 위와 같습니다, (설명을 위해 메모리 주소가 규칙적으로 되어있지만 실제 프로그램에서는 완전 랜덤한 메모리 주소로 변경됩니다.)

 

사진에서 보면 알 수 있듯이 a가 저장(참조)하고 있는 메모리 주소가 계속해서 바뀜을 알 수 있습니다, 변수가 계속해서 할당과 재할당이 일어남으로 a라는 식별자가 참조하고 있는 메모리 주소가 계속해서 바뀌는 것 입니다.

 

그러면 a 식별자가 더이상 참조하지 않는 값은 저렇게 메모리 상에서 쓰레기 값으로 남게 되는 것 일까요?

 

그렇지 않습니다, 자바스크립트는 메니지드 언어이기 때문에 메모리 관리를 해주는 가비지 콜랙터라는 것이 존재합니다.

가비지 콜랙터 (Garbage Collecter) : 자바스크립트 내에서 메모리를 관리(모니터링)하고 있는 기능입니다, 개발자가 직접적으로 접근이 아예 불가능합니다, 가비지 콜랙터는 프로그램 상에서 더이상 참조(사용)되지 않는 메모리 주소를 확인한뒤 자동으로 참조를 해제하고 제거하는 역할을 수행합니다.

정확히 말하자면 위의 예시같은 과정만 재할당이 아니라 아래의 코드도 결국에는 재할당의 개념입니다.

var a = 10;

왜냐하면, a 변수가 undefined로 초기화 되어 있는 상태에서 10을 새롭게 할당했기 때문에 재할당이라고 볼 수 있습니다. 

 

즉, 모든 변수 선언문은 기본적으로 값을 할당하는 순간 재할당이 일어난다고 생각할 수 있습니다.

정리하며

웹해킹을 더 깊게 공부하기 위해 기초를 다지는 시간으로 앞으로 계속해서 워게임 보다는 자바스크립트를 Deep 하게 공부하고 정리해나갈 예정입니다.

 

앞으로 정리하는 모든 [JavaScript Deep 하게 공부하기] 카테고리는 "모던 자바스크립트" 서적을 참고해서 작성하는 것 입니다.

 

변수를 일반적으로 사용만 하는 것이 아닌, 위와 같이 어떻게 돌아가는지 엔진은 변수를 어떤식으로 처리하는지를 알아야 취약점을 나중에 찾을때에도 더 깊이 있는 취약점을 찾을 수 있을 것 이라고 생각하빈다.

 

해당 파트를 공부하면서 변수의 사용성과 원리, 자바스크립트 엔진 관점에서의 해석 등을 새롭게 배울 수 있었습니다.

반응형
LIST