자바스크립트를 사용할때 변수의 타입으로 var
을 사용하곤 했는데, 인텔리제이 Ultimate 버전을 사용할때 IDE에서 var
대신 let
을 타입으로 변경할것을 권하는 alert를 자주 보곤 했다. 그 이유를 정리하려고 한다.
Why
우선 let
이라는 타입은 ES6(ECMAScript6)에서 추가된 문법이라고 한다. 그럼 왜 ES6에서 새로운 타입이 추가된걸까?
아래 예제 코드를 보자.
JS 코드를 보면, var
로 선언된 x
가 같은 함수내에서 중복 선언된걸 알 수 있다. 그럼에도 에러없이 마지막에 선언된 x
가 valueX
의 HTML에 입혀져서 출력이되었다.
짧은 코드이기에 이런 코드는 금방 수정할 수 있지만, 만약 수백줄, 수천줄의 코드에서 이런 문제가 있다면 이땐 어떻게 찾아야할까?
중복 선언이 된다면 실제 변수가 호출되는 시점에 따라 다른 값이 사용될수 있으므로 매우 혼란스러울것 같다.
또 한가지가 있다.
브라우저 콘솔창에서 아래와 같이 입력을 했다.
1 | console.log(name); |
1 | console.log(age); |
변수를 선언할때 타입을 각각 var
과 let
으로 호출하고, 변수 선언에 앞서 먼저 변수를 호출해서 콘솔에 출력하는 코드이다. 결과는 어떨까?
var
로 선언했을 경우는, 변수 name
이 선언되기도 전에 호출할 수 있었다. 물론 인터프리터 언어다보니 어떤 값이 있는지는 알수 없었다. 그러나 선언도 하지 않은 변수를 에러없이 undefined
로 출력할 수는 있었다.
반면 let
으로 선언한 변수 age는 Reference Error가 발생되어 콘솔에 아무것도 출력할수 없었다.
이것만으로 충분히 var
을 사용하는 일이 혼란스럽지만 한가지 사례를 더 찾아보았다.
1 | console.log(name); |
아예 블럭으로 스코프는 분리한 상태에서 콘솔에 실행해보았다. 결과는 어떨까? var
과 let
으로 변수를 선언했을때를 동시에 실행해보았다.
예측했겠지만, let
로 선언했을때는 이번에도 Reference Error가 발생했다.
반면 var
로 선언했을때에는 아까보다 한술더떠 다른 스코프의 값을 가져오는데도 성공했다.
이처럼 하위 스코프에서 선언되고 값이 할당된 변수를 끌어올려서 호출할 수 있는 기능을 호이스팅(Hoisting)이라고 한다. 자바 스크립트에서 컨텍스트가 실행되기 때문이라고 하는데, 컨텍스트에 대해서는 나중에 더 정리해볼 예정이다.
더 알아보기
var
로 변수를 선언하면 매우 혼란스럽다;; 이런 문제를 해결하기 위해 ES6에서 let
이 등장했다.
Benefit
위의 CodePen의 코드에서 중복선언된 x
의 타입을 let
으로 바꿔보자. 그리고 버튼을 클릭하여 함수를 실행하면, 화면에서 값이 바뀌지 않을것이다.
브라우저 콘솔에서 테스트하면 원인을 알 수 있다.
1 | let x = 100; |
변수 x
의 재정의로 인해 SyntaxError가 발생했다.
결과적으로 let
을 사용하면 변수의 중복선언이 불가능하기 때문에 안전하게 변수를 선언/사용할 수 있다.
var
과 let
의 차이중 또 하나 특징이 있다.
위의 CodePen에서 오른쪽 Result 탭에서 버튼을 클릭해보자. 클릭하기 전 각각 x
와 y
가 어떤 값이 할당될지 생각해보고 클릭해보자.
x
는 기대했던대로 변화되었지만, y
는 아닐것이다. 왜 그런걸까?
main()
함수를 살펴보자.
1 | function main () { |
스코프(scope)를 구분하기 위해 일부러 함수내에서 if문을 작성해서 스코프를 구분했다.
먼저 살펴볼 부분은 변수 x
가 중복선언되었다는 점이다. 앞서 let
으로 변수를 선언하면 중복선언이 불가능하다고 했다. 그런데 위의 코드는 어떻게 중복선언이 가능했던걸까?
let x
가 선언된 스코프의 차이가 이를 설명한다.
가장 먼저 선언된 x
는 main 함수를 스코프로 갖는다. 두번째로 선언된 x
는 if절을 스코프로 갖는다. 따라서 x
는 중복선언된게 아니라 서로 다른 스코프에서 선언된 변수일뿐이다.
따라서 실행화면에서 출력된 x
의 값은 1이 아닌 innerHTML
가 선언된 스코프의 x
값을 가져와서 2가 출력된 것이다.
같은 이유로 y
는 값이 출력되지 못했다. y
가 선언된 스코프는 if절인데, y
의 값을 출력하는 코드인 innerHTML
가 선언된 스코프보다 if절이 하위 스코프이기 때문에 y
의 값을 가져올수 없었다.
정상적으로 y
를 출력하려면 어떻게 해야할까?
if절 안에서 y
를 var
로 선언하는것으로 바꾸고 다시 버튼을 클릭하면 기대했던대로 출력될 것이다.
그러나 이렇게 전역변수를 사용하기 위해 var
을 사용하는건 권고되지 않는 방식의 코딩이다. 보다 나은 코드는 변수 y
는 let
으로 선언하되 HTML을 변경하는 innerHTML
코드를 if절 안으로 가져오는 것이다.
정리
let
의 사용목적은 아래와 같다.
- 변수 중복 선언 불가
- 스코프 규칙 준수
더 알아보기
const
ES6에서는 let
뿐만 아니라 const
가 추가되었는데, const
는 상수를 선언할때 사용한다. 즉 immutable 하게 사용할 변수는 let
이 아니라 const
로 선언해야 변수의 값을 안전하게 보존할 수 있다.