이번 게시글에서는 자바스크립트 변수에 대해 다뤄보도록 할 것이다. 자바스크립트에서 변수를 선언할 때는 다음과 같이 var나 let을 사용한다.
var name = "minsan";
let age = 22;
자바스크립트는 C, JAVA 등과 같은 기존 프로그래밍 언어와 달리 변수를 선언하거나 사용하는 것에 있어서 제약이 적다(Dynamic Typing - dynamically typed language). 예를 들어 기존 프로그래밍 언어(type이 static한 성질을 가짐)에서는 변수를 처음 선언할 때 해당 변수의 자료형을 명시해야하고, 변수를 먼저 선언한 '이후'에 값을 할당하거나 사용할 수 있다.
이와 달리, 자바스크립트에서는 변수를 선언할 때 자료형을 따로 명시할 필요가 없으며 var나 let 하나로 끝난다. 이렇게 자료형을 지정하지 않는 특징은 타입을 자유자제로 변경할 수 있어 코드를 작성하기 편리하다는 장점이 있지만, 예외적인 상황에서 발생할 수 있는 문제점을 처리하는 것이 어렵다는 문제가 존재한다. 다시 말해, 코드를 작성하는 당장에는 편리하겠지만 구동하는 데 있어서 많은 문제점이 발생한다. (즉, 코딩하면서 조심해야할 에러중 하나인 RuntimeError 가 발생하기 쉽다. 이를 해결하도록 나온 것이 바로 TypeScript(TS)이다. 자바스크립트를 다 배우고 나면 타입스크립트도 배워볼 예정이다.)
게다가 var를 사용하는 경우에는, 변수(var)를 선언하기 이전에 변수를 호출, 할당할 수 있다(Hoisting - 변수 선언부를 코드의 상단으로 끌어올림).
이러한 var 의 문제점을 보완할 수 있는 것이 바로 let 이다. let은 hoisting 하지 않고, 지역변수와 전역변수의 구분이 존재한다(var는 이러한 구분이 존재하지 않는다). 지역변수 전역변수는 자바스크립트 외의 기본적인 내용이므로 여기서는 다루지 않을 것이다
이렇듯 var는 기존 프로그래밍 방법과 상반되는 부분들이 존재하기 때문에, 자바스크립트에서 변수를 선언할 때 웬만하면 var는 사용하지 않는 것이 좋다.
앞으로 자바스크립트에서 변수를 선언할 때는 var가 아닌 let을 사용하도록 한다.
서두는 이정도로 마치도록 하겠다. 앞서 언급한 let과 var를 제외하고, 본격적으로 자바스크립트의 여러 자료형을 알아보도록 하겠다.
1. const (Immutable data type)
첫 번째로 constant(상수)의 약자를 딴 const이다. 일단 const는 엄연히 말하면 변수가 아니다. 변수는 말 그대로 변할 수 있는 값이다. 반면 상수는 처음 값이 정해지면, 그 이후에는 그 값은 변할 수 없다. 앞에서 말한 let과 var는 read & write이 가능하지만, const는 처음 값이 할당된 이후에는 read only. 여기서 let과 var와 같은 변수를 Mutable data type으로, const와 같은 것은 Immutable data type으로 분류된다. (하지만 변수나 상수 둘 다 레퍼런스 방식을 따르는 것은 동일하다)
favor Immutable data type always for a few reasons:
- security
- thread safety
- reduce human mistakes
const name = "minsan"
name = "min" // error
2. symbol (Create unique identifiers for objects)
작업을 하게 되면 자주 사용되는 클래스(?)라고는 하는데, 어디서 어떤 경우에 사용되는건지 사실 아직 감이 잘 잡히지 않는다. 그래도 나중에 많이 사용하게 될 것이라고 하니 일단은 익혀두자.
symbol은 다음과 같이 사용한다.
const symbol = Symbol('id');
이 symbol을 사용할 때 조금 주의해야할 점이 있다. 파라미터로 전달하는 문자열이 동일함에도 불구하고, 서로 다른 심볼을 생성한다는 점이다. 이해하기 쉽게 코드로 다시 한번 살펴보겠다.
const symbol1 = Symbol('id');
const symbol2 = Symbol('id');
console.log(symbol1 === symbol2); // false
만약 문자열에 매칭되는(문자열에 따라 생성되는 즉, 위의 경우에서는 동일한 심볼이 생성되는) 심볼을 생성하기 위해서는 다음과 같이 for 메소드를 이용해야 한다.
const symbol_1 = Symbol.for('id');
const symbol_2 = Symbol.for('id');
console.log(symbol_1 === symbol_2); // true
추가로 이 심볼을 출력할 때는 다음과 같이 description을 사용해야 한다.
console.log(`value: ${symbol_1.description}, type: ${typeof symbol_1}`);
3. object
const min = {'name': 'min', age: 22};
이 오브젝트는 나중에 다루게 될 클래스와 연결되는 부분이기도 하다. 아무튼 이 예제와 같이, 객체 내에서는 여러 변수를 지정하고 할당할 수 있다. 메모리에서 이 객체를 저장할 때는, 레퍼런스(reference)를 저장하게 된다. 여기서 레퍼런스란, 해당 값이 저장된 '메모리에 접근'하여 값을 읽어들이는 것을 의미한다. 이 레퍼런스에서는 값 그 자체가 아니라 메모리에 접근한다는 것이 핵심이다. (예로 게시글에서 출처와 함께 원글 링크를 달아놓는 것을 떠올려보자. 게시글 내에서는 원글에 대한 내용(값)을 모두 다루지는 않지만, 링크(레퍼런스)를 통해 원글에 접근할 수 있는 것이다. 즉, 레퍼런스는 값이 저장된 곳에 접근하는 통로 역할을 한다고 생각하면 쉽다. 포인터는 하나의 레퍼런스 방식이다.)
어쨌든, 앞의 내용을 종합해서 다시 설명해보겠다. 만약 코드에서 min을 호출하게 되면, 메모리상에 이 min이라는 오브젝트가 저장된 메모리에 접근할 것이다(변수는 자신이 담고있는 값이 저장되어 있는 메모리를 가리키기 때문이다 - 포인터). 이때 이 메모리에는 min이라는 오브젝트 내에 저장된 '값'들을 담고있는 것이 아니라, 이 오브젝트 내에 저장된 '값이 담긴 메모리'를 즉, 레퍼런스를 저장하고 있는 것이다.
이 예제에서 min을 호출하게 되면, 해당 메모리에는 name과 age에 각각 저장된 값에 접근할 수 있는 레퍼런스가 저장되어 있다. 우리는 이를 다음과 같이 접근하고 사용할 수 있는 것이다.
console.log(min.name); // 'min'
console.log(min.age); // 22
min.name = "minsan";
min.age = 23;
console.log(min.name); // 'minsan'
console.log(min.age); // 23
오브젝트 내에 있는 name, age라는 변수에 접근하는 것은 레퍼런스이기 때문에, 메모리에 접근하여 값을 변경하는 것이 가능하다. 하지만, 앞에서 min을 선언했을 때 const로 선언했기 때문에 다음과 같이 오브젝트 자체를 수정하는 것은 불가능하다.
min = {'name': 'minsan', age: 23, major: 'CS'}; // not allowed
어쩌다보니 글이 생각보다 길어진 것 같다. 참조(reference) 개념을 처음 접했을 때 헷갈렸던 부분이 정말 많았기 때문에, 이번 기회에 한번 제대로 정리하고 넘어가자는 생각으로 글을 작성해보았다. 내 방식대로 주절주절 쓰다보니 정리가 잘 안된 것 같은 느낌이 들지만, 글을 작성하면서 레퍼런스 개념을 다시한번 짚고 넘어갈 수 있었던 것 같다.
'frontend > javascript' 카테고리의 다른 글
[JavaScript] 05 Objects (0) | 2021.09.02 |
---|---|
[JavaScript] 04 Class (0) | 2021.08.26 |
[JavaScript] 03 Operators (0) | 2021.08.26 |
[JavaScript] 02 Function (0) | 2021.08.26 |
[JavaScript] 자바스크립트 (0) | 2021.08.25 |