(자알쓰) 변수

자알쓰란?

바스크립트 자. (잘 쓰자는 의미도 담겨있다.)
자바스크립트라는 언어 자체는 내 기준에서는 설계 상 미스가 참 많다.
함수 단위의 스코프, 호이스팅, 동적 타입 등등
자바와 같은 깐깐(?)한 언어를 배우고 바라본 자스는 허점 투성이처럼 보였다.
애초에 자바스크립트는 어떠한 프로그램을 만들기 위해서 탄생했다기 보다는
웹 페이지에 입력값에 대한 유효성 검사(데이터가 공란인지 아닌지 등등)와 같은
페이지의 동적 제어가 주된 목적 + 짧은 개발 기간(넷 스케이프 사의 새로운 브라우저에 탑재 예정) 때문에
설계 상에 미스가 있을 수 밖에 없다고 나는 생각된다.
일종의 안전 장치가 없어서 개발자가 일일이 구현해주고, 신경써야 하는 느낌이었다.
그렇다고 해서 자바스크립트를 극혐하거나 그런 것은 아니고 매우 사랑한다.
또한 그 허점을 아는 사람은 허점을 보완해서 요리조리 피해서 잘 쓰겠지만…
잘 모르는 부분들은 잘못 써도 동작이 잘 되기 마련이다.
이는 지금 당장에는 큰 문제가 안 될지 모르겠지만, 추후에 대규모 웹 어플리케이션을 만들거나
직면할 문제로부터 미리 해방시키기 위해 처음부터 좋은 습관을 들여가는 것이 좋다고 생각한다.
그 열 한 번째 시리즈는 변수를 주제로 진행하겠다.

변수란?

이번 주제는 정재남 님의 자바스크립트 세미나를 듣고 해당 자료를 토대로 내 맘대로 해석한 포스트이다.

책을 보다보면 변수는 그냥 값들을 담아놓는 상자 정도로 설명해놓는다.
과연 이게 변수의 끝일까? 정말 변수는 이렇게 작동할까?

뜬금없이 RAM이 왜 등장했냐 하면…
컴퓨터의 프로그램이 실행되려면 모두 RAM에 해당 소스가 존재해야한다.
그 말은 RAM에 우리가 짠 자바스크립트 소스, 변수가 어딘가에 존재한다는 것이다.
하지만 RAM은 Random Access Memory, 즉 랜덤하게 데이터가 들어가게 된다.
var a = 2; 라고 해서 어디에 우리의 데이터가 들어가있는지 알지 못한다.
var a = 2; 라고 하면 2라는 값이 저장된 메모리 주소가 어딘가 있을 거다.
그 때 그 주소가 0x1234라고 가정했을 때 변수가 많다보니 모든 변수의 메모리 주소를 외우는 것은 불가능하다.
따라서 해당 메모리 주소에 이름을 붙인 것이 바로 변수이다.
마치 네이버의 ip 주소(125.209.222.141)를 다 외우지 못해 www.naver.com으로 치는 격이다.
ip 주소가 메모리 주소고, 도메인 네임이 바로 변수라고 보면 될 것 같다.

변수의 초기화 과정

이는 호이스팅과 묶어서 보면 좋을 것 같다.
아래와 같은 코드가 있다고 치자.

1
2
3
4
5
6
var a = 2;
console.log(a); // 2
console.log(b); // undefined
var b = a;
console.log(b); // 2
console.log(c); // ReferenceError: c is not defined

호이스팅 때문에 위 코드는 아래와 같이 바뀌게 될 것이다.

1
2
var a;
var b;

그럼 위 과정과 메모리를 엮어서 한 번 봐보자.
a와 b는 메모리 주소에 이름을 붙인 것이고, 실제 데이터는 해당 메모리 주소에 저장이 된다.

a b 0x1234 0x1235
0x1234 0x1235
1
2
3
var a;
var b;
a = 2;

그리고 3번 라인에 의해 아래와 같이 바뀐다.

a b 0x1234 0x1235
0x1234 0x1235 2
1
2
3
4
5
6
7
8
var a;
var b;
a = 2;
console.log(a); // 2
console.log(b); // undefined
b = a;
console.log(b); // 2
console.log(c); // ReferenceError: c is not defined

그리고 6번 라인에 의해 아래와 같이 바뀐다.

a b 0x1234 0x1235
0x1234 0x1235 2 2

원시값은 위와 같이 메모리의 새로운 영역에 값을 ‘복사’하는 형태로 가고 있다.
그럼 참조 타입인 객체들을 어떻게 만들어지는지 한번 살펴보자.

1
2
3
4
5
6
var a = {
name: '양권성',
friends: ['양간장', '간장냥'],
age: 25
};
var b = a;

그럼 이제 위 데이터들을 하나씩 까보자.

1
2
var a;
var b;

먼저 호이스팅에 의해 아래와 같이 메모리를 잡을 것이다.

a b 0x1234 0x1235
0x1234 0x1235
1
2
3
4
5
6
7
var a;
var b;
a = {
name: '양권성',
friends: ['양간장', '간장냥'],
age: 25
};

그리고 3번에 의해 아래와 같이 바뀔 것이다.

a b 0x1234 0x1235 0x1236 0x1237 0x1238 0x1239 0x1240
0x1234 0x1235 0x1236 { name: 0x1237, friends: 0x1238, age: 0x1239 } 양권성 0x1240 25 [‘양간장’, ‘간장냥’]
0x1236의 객체를 보면 name, friends, age라는 키에 해당하는 값들도 어딘가 메모리에 적재가 돼있을 것이다.
그 메모리 주소에 대한 이름을 키라고 보면 될 것 같다.
그리고 friends는 원시값이 아니고 참조값이기 때문에 해당 메모리 주소로 이동하면 또 메모리 주소가 있고,
그 메모리 주소를 타고 가야 비로소 우리가 원하는 값이 있다.
1
2
3
4
5
6
7
8
var a;
var b;
a = {
name: '양권성',
friends: ['양간장', '간장냥'],
age: 25
};
b = a;

마지막 라인에 의해 아래와 같은 결과가 나오게 된다.

a b 0x1234 0x1235 0x1236 0x1237 0x1238 0x1239 0x1240
0x1234 0x1235 0x1236 0x1236 { name: 0x1237, friends: 0x1238, age: 0x1239 } 양권성 0x1240 25 [‘양간장’, ‘간장냥’]

객체는 거의 무한한 데이터를 담을 수 있으므로 복사보다는 참조하는 것이 메모리를 더 절약하기 때문인지 객체를 참조 타입으로 지정한 것 같다.
역시 이런 기초 기반 지식들이 상당히 중요한 것 같다.