Development/Etc

[모던 자바스크립트] var를 사용하지 않아야 하는 이유

bbubbush 2022. 9. 3. 08:45

들어가며

ES6에서는 변수를 사용하기 위해 새로운 문법인 let과 const를 지원하면서 동시에, var의 사용을 지양하라고 권한다. 그렇다면 var는 어떤 문제가 있기에 새로운 대체 문법이 생겼는지, 어떤 차이가 있는지 살펴보자.

 

우선은 var의 문제점 세 가지를 살펴보자.

 

var의 세 가지 문제점

1. 선언을 중복해서 할 수 있다

var code = 10;
var code = 20;
console.log(`code: ${code}`);  // 'code: 20'

같은 이름의 변수를 중복해서 선언해도 정상적으로 동작하며, 가장 마지막 값을 저장하고 있는다.

 

2. scope의 범위가 전역 / 함수로 제한된다

var code = 10;
if (true) {
  var code = 0;
  var codeName = 'Hello JS!';
}
console.log(`code: ${code}`);  // 'code: 0'
console.log(`codeName: ${codeName}`);  // 'codeName: Hello JS!'

if 구문 안에서 새로운 변수를 사용했지만 기존 변수에 데이터가 재할당 되었다. 위에서 본 '1) 선언을 중복해서 할 수 있다'와 동일하게 동작했다. 이를 통해 if 구문 안의 scope는 전역(Global)과 동일하게 취급받는 것을 알 수 있다.

 

3. Hoisting이 가능하다

console.log(`Before declare: ${code}`);  // 'Before declare: undefined'
var code = 10;
console.log(`After declare: ${code}`);  // 'After declare: 10'

JS는 변수의 선언이 실행 시점(Runtime)에 동작할 것 같지만 실행 전에 변수와 함수를 미리 실행한다. 함수만 정의해 놓았는데 자동으로 실행되는 경험이 한 번씩은 있었을 것이다. 이것은 정의된 함수가 실행 시점보다 이전에 동작하기 때문이다.

마찬가지로 변수도 실행 시점 전에 동작한다. 그래서 위 코드처럼 선언되기 전의 변수를 사용하는 코드가 가능하다. 이를 호이스팅이라고 한다.

 

 

이렇게 var의 세 가지 문제점을 살펴보았다. 이 문제점이 와닿지 않았다면 본인도 모르게 위의 문제를 회피하는 코딩 습관이 있다고 생각해도 좋다. 하지만 ES6부터 let과 const라는 좋은 대안이 생겼다. 이들이 어떻게 문제를 해결하는지 하나씩 살펴보자.

 

반응형

 

개선된 let과 const

1. 선언을 중복할 수 없다. 때에 따라선 재할당도 할 수 없다

let은 기존의 var를 대체하는 ‘변수’의 역할을 한다. const는 기존에 없던 ‘상수’의 역할을 담당하며 새롭게 등장했다.

let은 중복된 선언이 문법으로 불가능하다. 그래서 전역에서 중복된 이름이 정의된다면 바로 오류가 난다.

let code = 10;
let code = 20;  // SyntaxError: Identifier 'code' has already been declared.

반면 재할당은 가능하다. 그것이 변수의 역할이니까!

let code = 10;
code = 20;
console.log(`code: ${code}`);  // 'code: 20'

 

const는 상수의 역할이므로 선언과 동시에 할당이 되어야 하며 중복 선언, 재할당 모두 불가능하다.

const code;  // SyntaxError: Missing initializer in const declaration.
const code = 10;
code = 0;  // TypeError: Assignment to constant variable.

 

단순히 var를 let으로 선언하기만 해도 중복된 변수명으로 발생하는 문제를 예방할 수 있다.

 

2. block 단위의 scope를 사용할 수 있다

var는 함수와 전역, 두 경우를 제외하고 scope를 적용할 수 있는 방법이 없었다. 따라서 if, for 구문 안에서 사용한 변수는 전역 혹은 함수 안에서 살아있게 된다. 내가 사용하는 변수가 다른 개발자에 의해 값이 변경될 수 있다는 뜻이다. 생각보다 사람들이 변수명을 비슷하게 만들기 때문에 언제나 가능성은 열려있다.

 

var와 const는 블록 단위로 살아있는다. 그래서 codeName을 더 이상 전역에서 사용할 수 없게 된다.

let code = 10;
if (true) {
  let code = 0;
  let codeName = 'Hello JS!';
}
console.log(`code: ${code}`);  // 'code: 10'
console.log(`codeName: ${codeName}`);  // ReferenceError: codeName is not defined
const code = 10;
if (true) {
  const code = 0;
  const codeName = 'Hello JS!';
}
console.log(`code: ${code}`);  // 'code: 10'
console.log(`codeName: ${codeName}`);  // ReferenceError: codeName is not defined

변수의 scope가 좁아질수록 버그의 발생이 줄어든다. 중복된 변수명을 사용해도 범위가 좁다면 문제없이 동작한다.

 

3. Hoisting이 불가능하다

console.log(`Before declare: ${code}`);  // ReferenceError: Cannot access 'code' before initialization
let code = 10;
console.log(`After declare: ${code}`);

let과 const는 더 이상 실행 시점에 동작하지 않는다. 이로 인해 변수의 라이프사이클이 상식적으로 되었다. 당연히 변수를 선언한 시점부터 변수를 사용할 수 있어야 자연스럽지 않을까?

 

 

마치며

간혹 프로젝트를 진행하다 보면 ‘왜 let과 const를 사용해요?’라고 묻는 개발자들이 있다. 하나씩 설명하기 귀찮아서 그냥 웃고 넘겼다. 아마 그들은 여전히 var를 쓰면서 생기는 문제로 여전히 고통받으면서 불평만 늘어놓고 있을 것이다. 나는 여전히 웃고 넘기겠지만.

 

이제는 선택이 아니라 필수로 적용해야 한다. 그래야 내 코드가 다른 개발자에게 영향을 주지 않는다는 확신이 생기기 때문이다. 코드 간의 결합도를 낮추는 것이 근본적인 문제 해결 방법이라는 것을 잊지 말아야 한다.

 

 

[모던 자바스크립트 관련 글]

 

[모던 자바스크립트] Array 스마트하게 사용하기

들어가며 배열(Array)은 맵과 함께 데이터를 관리하기 위한 가장 효율적인 자료구조다. 이번에는 배열로 무엇을 할 수 있는지 보면서 for 구문의 지옥에서 벗어날 수 있는 것을 목표로 한다. 고전

bbubbush.tistory.com

 

[모던 자바스크립트] Object 기깔나게 사용하기

들어가며 자바스크립트에서 맵(Map)은 ES6가 되어서야 등장했다. 다른 언어에 비하면 상당히 늦은 편이다. 왜일까? 바로 객체(Object)라는 대안이 있었기 때문이다. 따라서 맵을 어떻게 사용하는지

bbubbush.tistory.com

 

[모던 자바스크립트] 어썸한 Funtion 변경사항

들어가며 자바스크립트는 함수로 대표된다고 해도 과언이 아니다. 이제는 객체지향적인 방식으로 작업하는 개발자도 많지만 과거부터 함수를 정의하고 사용해왔기에 아직까지 함수 지향적인

bbubbush.tistory.com

 

[모던 자바스크립트] Promise 한 방에 뿌수기

들어가며 아마 ES6의 내용 중 이해하기 가장 어려운 내용이 프로미스가 아닐까 생각한다. 다른 변경사항은 기능에 충실한 반면, 프로미스는 특정한 상황을 해결하기 위해 등장했기 때문이라 생

bbubbush.tistory.com

 

[모던 자바스크립트] 이름은 Optional, 적용은 Required

들어가며 ES6부터 객체의 값을 안정적으로 가져오는 옵셔널이 도입됐다. 개념도 쉽고 적용하기도 쉽기 때문에 활용도가 높다. 더 이야기할 게 없으니 바로 알아보자 🙂 전통적인 객체 프로퍼티

bbubbush.tistory.com