(자알쓰) 변수
자알쓰란?
자
바스크립트 알
고 쓰
자. (잘 쓰자는 의미도 담겨있다.)
자바스크립트라는 언어 자체는 내 기준에서는 설계 상 미스가 참 많다.
함수 단위의 스코프, 호이스팅, 동적 타입 등등
자바와 같은 깐깐(?)한 언어를 배우고 바라본 자스는 허점 투성이처럼 보였다.
애초에 자바스크립트는 어떠한 프로그램을 만들기 위해서 탄생했다기 보다는
웹 페이지에 입력값에 대한 유효성 검사(데이터가 공란인지 아닌지 등등)와 같은
페이지의 동적 제어가 주된 목적 + 짧은 개발 기간(넷 스케이프 사의 새로운 브라우저에 탑재 예정) 때문에
설계 상에 미스가 있을 수 밖에 없다고 나는 생각된다.
일종의 안전 장치가 없어서 개발자가 일일이 구현해주고, 신경써야 하는 느낌이었다.
그렇다고 해서 자바스크립트를 극혐하거나 그런 것은 아니고 매우 사랑한다.
또한 그 허점을 아는 사람은 허점을 보완해서 요리조리 피해서 잘 쓰겠지만…
잘 모르는 부분들은 잘못 써도 동작이 잘 되기 마련이다.
이는 지금 당장에는 큰 문제가 안 될지 모르겠지만, 추후에 대규모 웹 어플리케이션을 만들거나
직면할 문제로부터 미리 해방시키기 위해 처음부터 좋은 습관을 들여가는 것이 좋다고 생각한다.
그 열 한 번째 시리즈는 변수를 주제로 진행하겠다.
변수란?
이번 주제는 정재남 님의 자바스크립트 세미나를 듣고 해당 자료를 토대로 내 맘대로 해석한 포스트이다.
책을 보다보면 변수는 그냥 값들을 담아놓는 상자 정도로 설명해놓는다.
과연 이게 변수의 끝일까? 정말 변수는 이렇게 작동할까?
뜬금없이 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
6var 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
2var a;
var b;
그럼 위 과정과 메모리를 엮어서 한 번 봐보자.
a와 b는 메모리 주소에 이름을 붙인 것이고, 실제 데이터는 해당 메모리 주소에 저장이 된다.
a | b | 0x1234 | 0x1235 |
---|---|---|---|
0x1234 | 0x1235 |
1 | var a; |
그리고 3번 라인에 의해 아래와 같이 바뀐다.
a | b | 0x1234 | 0x1235 |
---|---|---|---|
0x1234 | 0x1235 | 2 |
1 | var a; |
그리고 6번 라인에 의해 아래와 같이 바뀐다.
a | b | 0x1234 | 0x1235 |
---|---|---|---|
0x1234 | 0x1235 | 2 | 2 |
원시값은 위와 같이 메모리의 새로운 영역에 값을 ‘복사’하는 형태로 가고 있다.
그럼 참조 타입인 객체들을 어떻게 만들어지는지 한번 살펴보자.1
2
3
4
5
6var a = {
name: '양권성',
friends: ['양간장', '간장냥'],
age: 25
};
var b = a;
그럼 이제 위 데이터들을 하나씩 까보자.1
2var a;
var b;
먼저 호이스팅에 의해 아래와 같이 메모리를 잡을 것이다.
a | b | 0x1234 | 0x1235 |
---|---|---|---|
0x1234 | 0x1235 |
1 | var a; |
그리고 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 | var a; |
마지막 라인에 의해 아래와 같은 결과가 나오게 된다.
a | b | 0x1234 | 0x1235 | 0x1236 | 0x1237 | 0x1238 | 0x1239 | 0x1240 |
---|---|---|---|---|---|---|---|---|
0x1234 | 0x1235 | 0x1236 | 0x1236 | { name: 0x1237, friends: 0x1238, age: 0x1239 } | 양권성 | 0x1240 | 25 | [‘양간장’, ‘간장냥’] |
객체는 거의 무한한 데이터를 담을 수 있으므로 복사보다는 참조하는 것이 메모리를 더 절약하기 때문인지 객체를 참조 타입으로 지정한 것 같다.
역시 이런 기초 기반 지식들이 상당히 중요한 것 같다.