안녕하세요!
이번 포스트에서는 JavaScript & Node.js 에서 변수 선언 시에 사용되는 var, let, 그리고 const 키워드들에 대하여 알아보도록 하겠습니다. 우리는 이미 var 키워드를 사용하여 변수를 선언할 수 있다는 것을 알고 있습니다 (모르셨다면 이제 아신 겁니다). 그렇다면, 그렇게 천재적인 사람들이 어찌하여 let 가 const 키워드를 추가하게 된 것일까요? 지금 이 순간, 그것에 대하여 낱낱이 파헤쳐 보도록 하겠습니다.
Image Ref: Medium
var 키워드
var 키워드는 ES6 (ECMAScript 6) 가 도입 되기 전에 JS 에서 변수를 선언하기 위하여 사용 되던 키워드 입니다. 물론 지금도 존재하고 아직도 많은 분들이 사용하고 계시죠. 이번 포스트는 자바스크립트의 스코프 (Scope) 와 아주 밀접한 연관이 있으므로, 아직 자바스크립트 스코프의 개념에 대해 잘 모르고 계시다면, 아래 포스트 혹은 직접 스코프를 공부하신 후에 이 글을 읽으시는 것을 적극 추천 드립니다!
2022.04.07 - [Studying/JavaScript & Frameworks] - [JavaScript 떠먹여 주는 남자] 스코프 (Scope)
위 포스트의 마지막에 제가 아주 의미심장한 내용을 하나 남겼었드랬죠 (궁금하시면 보고 오시죠 😏 )
.
.
.
.
.
.
.
.
.
.
.
그것은 바로 var 키워드를 사용하면 같은 스코프 내에서 중복 선언이 가능하다는 것이었습니다. 간단한 코드로 설명 드리도록 하겠습니다.
// while 코드 블록
var globalVariable = 1;
while (true) {
var globalVariable = 10;
break;
}
console.log(globalVariable);
// for 코드 블록
var idx = 100;
// for문에서 선언한 idx는 전역 변수이다. 이미 선언된 전역 변수 idx가 있으므로 중복 선언된다.
for (var idx = 0; idx < 5; idx++) {
console.log(idx); // 0 1 2 3 4
}
// 의도치 않게 idx 변수의 값이 변경되었다.
console.log(idx); // 5
위의 코드의 실행 결과값은 10 입니다. 위의 globalVariable 은 변수명에서도 알 수 있듯이 전역 스코프 내에서 선언 된 변수입니다. 그 말인 즉슨 '전역 스코프 내에 있는 어느 곳에서도 저 변수를 참조할 수 있다' 는 것이죠. 또 하나, var 키워드로 선언한 변수는 오로지 함수의 코드 블록 (함수 몸체 혹은 바디) 만을 지역 스코프로 인정합니다. 다시 말해, if, for, while, try/catch 등의 코드 블록에서 var 키워드로 선언 된 변수는 전역 변수가 된다는 말입니다.
한 가지 더!
초기화문이 있는 변수 선언문은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작하고 초기화문이 없는 변수 선언문은 무시됩니다.
var x = 1;
var y = 1;
// var 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용한다.
// 초기화문이 있는 변수 선언문은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작한다.
var x = 100;
// 초기화문이 없는 변수 선언문은 무시된다.
var y;
console.log(x); // 100
console.log(y); // 1
이제 왜 저 위의 JS Developer 가 죽음을 목전에 두고도 let 과 const 를 쳐다보는지 감이 잡히시나요? var 키워드를 이용하여 변수를 선언하게 되면, 혹시 개발자가 이전에 같은 변수명으로 선언 & 초기화 했던 것을 잊고 어딘가에서 다시 선언 & 초기화를 하게 되는 경우가 발생할 수도 있습니다. 만약 개발자의 의도대로라면 (왜 때문인지 모르지만) 상관 없겠지만, 그러지 않을 경우에는 예측하지 못한 어마무시한 결과를 초래할 가능성이 있습니다.
저는 언제나 let 과 const 를 쓰는데도 항상 이 고민을 안고 살아갑니다.
var 키워드를 사용하게 되면 이런 짜릿한 경험을 할 수 있는 가능성이 올라간다고 할 수 있을 것 같습니다. 그러니 ES6 를 사용하실 수 있는 환경이라면 제발 var 키워드 사용을 멈춰!
let 키워드
그렇다면, let 키워드를 사용함으로써 얻을 수 있는 장점들은 무엇들이 있는지 알아보겠습니다.
값의 재할당
이미 모두가 아시다시피 var 변수는 값의 재할당이 가능합니다. 하지만 위에 나열된 문제점들 때문에 사용을 지양하는 것을 권장하는데요, 그의 대체자로 등장한 것인 바로 let 키워드 입니다. let 키워드로 선언한 변수는 값의 재할당이 가능합니다.
변수 중복 선언 금지
// var 키워드로 변수 선언 시
var varGlobalVariable = 10;
var varGlobalVariable = 100;
console.log(varGlobalVariable); // 100
// let 키워드로 변수 선언 시
let letGlobalVariable = 1000;
let letGlobalVariable = 10000;
console.log(letGlobalVariable); // "Uncaught SyntaxError: Identifier 'letGlobalVariable' has already been declared"
이를 통해서 우리는 변수 중복 선언으로 인한 끔찍한 사태를 미연에 방지할 수 있게 됩니다.
블록 레벨 스코프
var 키워드를 통하여 선언 & 초기화 된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정한다고 이미 여러번 언급했습니다. 하지만 let 키워드로 선언한 변수는 모든 코드 블록을 지역 스코프로 인정하는 블록 레벨 스코프 (block-level scope) 를 따릅니다.
// while 코드 블록
let globalVariable = 1;
while (true) {
let globalVariable = 10;
break;
}
console.log(globalVariable); // 1
// for 코드 블록
let idx = 100;
for (let idx = 0; idx < 5; idx++) {
console.log(idx); // 0 1 2 3 4 5
}
console.log(idx); // 100
함수 역시 코드 블록이므로 스코프를 만듭니다. 이 때, 함수 내의 코드 블록은 함수 레벨 스코프에 중첩 됩니다.
const 키워드
이미 let 이 var 의 많은 단점을 커버해 줄 수 있는데, 왜 const 키워드가 존재하는 걸까요?
값의 재할당과 중복 선언 금지
const 키워드는 상수 (constant - immutable value) 를 선언하기 위해 사용됩니다. 변수의 의미는 변하는 값, 상수의 의미는 변하지 않는 값을 의미합니다. 따라서, let 의 경우 값의 재할당이 가능하기에 선언을 먼저 해주고 나중에 따로 값을 할당 해 줄 수 있지만, const 로 선언한 변수는 반드시 선언과 동시에 초기화를 해야 합니다. 당연히 중복 선언도 불가능합니다. 그래도 굳이 해보고 싶으신 분들이 계실 수 있기 때문에 킹받으시라고 제가 먼저 해보았습니다ㅋ
// 초기화 하지 않을 시
const foo; // Uncaught SyntaxError: Missing initializer in const declaration
// 중복 선언
const constVariable = 1;
const constVariable = 2; // Uncaught SyntaxError: Identifier 'constVariable' has already been declared
const 로 변수를 선언함으로써 상태 유지 (원시값의 재할당 불가능) 와 가독성, 유지/보수의 편의성을 모두 챙길 수 있게 됩니다. 프로그램을 작성하다 보면 고정값을 사용해 주어야 할 경우가 자주 있는데, const 는 바로 그런 목적을 위해 사용하도록 디자인 되었습니다.
객체 프로퍼티 값과 배열 엘레멘트 값의 재할당
위에서 분명 상수는 값의 재할당이 불가능하다고 했습니다. 하지만 그것은 원시값의 경우일 때만 해당 되는 내용입니다. 원시값은 int, char, string, boolean 등의 타입으로 할당 된 값을 의미합니다. 하지만, const 로 선언 된 객체 혹은 배열의 경우 각 프로퍼티 혹은 엘레멘트의 값을 변경하는 것이 가능합니다 😲 .
const primitiveValue = 1; // 원시값
primitiveValue = 2; // Uncaught TypeError: Assignment to constant variable.
const obj = { nickname: "AllenC", status: "exhausted" };
obj.status = "happy";
console.log(obj); // { nickname: "AllenC", status: "happy" }
const arr = [1, 2, 3, 4];
arr[0] = 5;
console.log(arr); // [5, 2, 3, 4];
적절한 키워드 사용 팁
- 만약 ES6 를 사용할 수 있는 환경이라면, var 는 사용하지 마시고 let 과 const 를 적극 활용 해 주세요.
- 대부분의 경우 const 로 먼저 변수 선언을 고려 해 주세요. 만약, 정말 값의 재할당이 필요한 경우에만 let 키워드를 사용하여 변수를 선언 해 주시고, 이 때, 변수의 스코프는 최대한 좁게 만들어 주세요 (let 을 사용한다고 해서 예기치 않은 상황이 발생하는 것을 100% 방지할 수는 없어요).
마무으리
처음 계획은 이 포스트 하나로 모든 개념을 정리 할 생각이었는데, 생각보다 담고 싶은 내용이 많아서 부득이하게 두 편으로 나누기로 결정했습니다. 다음 포스트에서는 번외편으로 변수 호이스팅과 전역 객체에 대한 내용을 커버하려고 합니다. 그럼 이번 포스트는 여기서 마무리 짓도록 하겠습니다. 내용이 조금 길지만 부디 여기까지 다 읽어 주시기 바라겠습니다. 지루한 글 읽어주시느라 모두 고생 많으셨습니다.
그럼 안녕~
'Studying > JavaScript & Frameworks' 카테고리의 다른 글
[똥쌀 때 보는 자바스크립트 개념] arguments 프로퍼티 (0) | 2022.04.12 |
---|---|
[자바스크립트 떠먹여 주는 남자] 스코프 (Scope) (0) | 2022.04.07 |
[Node.js 떠먹여 주는 남자] Promises vs. async/await in Node.js (1) (0) | 2022.04.03 |
[자바스크립트 떠먹여 주는 남자] Normal Function vs. Arrow Function (0) | 2022.04.02 |
[자바스크립트 떠먹여 주는 남자] JavaScript, ECMAScript, 그리고 VanillaJS (0) | 2022.04.02 |