- Dan Abramov 의 트윗 중에서
프로젝트는 끝이 났지만 잡서칭은 이제부터 시작입니다. 이력서와 자기소개서, 추가적인 개인 프로젝트 구상, 거기에 코딩 테스트와 기술 면접 대비까지. 개발자로 서기 위한 관문들이 저를 기다리고 있네요.
오늘은 기술 면접에서 자주 등장한다고 하는 질문인 "var, let, const, 그리고 호이스팅" 이라는 주제로 블로깅을 해보려고 합니다. 리덕스를 만든 Dan Abromov 는 트윗으로 "let, const 를 사용하는 이 마당에 왜 아직도 호이스팅에 관해 묻는지 이해할 수 없다"는 반응을 보이기도 했습니다만, 여전히 이 질문은 기술 면접의 단골 카테고리 중 하나라고 합니다.
오늘의 블로깅은 가급적 제가 이해하고 있는 바를 정리하는 차원에서 진행할 예정입니다. 이미 공부했던 내용을 바탕으로 풀어낼 예정이기 때문에 여기의 내용은 100% 정확하지 않을 수 있으며, 혹시라도 이 글을 보시는 분들은 참고 정도로만 사용해주시면 좋겠습니다.
var 는 변수를 선언할 때 사용하는 명령어입니다. 오늘날 현업에서는 절대 쓰이지 않는 명령어라고 하는데요. 저 역시도 공부를 시작한 이래로 var 를 써본 기억은 없습니다.
var 를 쓰지 않아도 된 결정적인 이유는 변수를 선언할 때 사용할 수 있는 let, const 라고 하는 새로운 명령어가 등장했기 때문입니다. 새로운 것이 등장한다는 것은 기존의 것에 대체할만한 무언가가 있기 때문이겠죠. 이 셋의 관계, 그리고 호이스팅을 이해하면 왜 var 라는 명령어가 사라지게 되었는지를 이해할 수 있게 됩니다.
var 라는 명령어는 재할당과 재선언이 가능한 명령어입니다. 그 말인즉슨, var name = "eensungkim"
이라는 코드를 작성한 뒤에 아래에서 다시 var name = "kimcoding"
이라고 작성해도 문제 없이 동작한다는 것이죠.
이렇게 될 때 발생하는 치명적인 문제점 중 하나는, 코드가 복잡해질수록 어디에선가 선언한 변수가 중첩되어 꼬여버릴 가능성이 생긴다는 것입니다. 저는 "eensungkim" 이라는 내용으로 코드가 동작하기를 원했는데 어느 시점 이후로 "kimcoding" 으로 동작한다면 문제가 생기겠죠.
그래서 let은 기본적으로 재선언이 불가능하도록 만들어졌습니다. 만약 재선언을 시도하면 에러가 뜨게 되죠. 대신 값을 재할당하는 것은 가능합니다. const 는 재선언은 물론 재할당도 불가능합니다.
let name = "eensungkim";
let name = "kimcoding"; // Uncaught SyntaxError: Identifier 'name' has already been declared
name = "parkhacker"; // let 은 재할당이 가능
const age = 20;
age = 25; // Uncaught TypeError: Assignment to constant variable.
그래서 일반적으로 권장되는 방법은 가능한 모든 선언에 const 를 사용하고, 불가피하게 재할당을 진행해야 하는 경우 let 을 사용하는 것입니다. let 과 const 가 완벽하게 var 의 역할을 대체하면서, 심지어 발생 가능한 오류도 줄여주니 var 를 사용해야 하는 이유가 사라지게 되었죠.
앞서 말한 재선언과 재할당이 가능하다는 문제 외에도 var 가 가진 또 다른 문제가 있었습니다. 바로 호이스팅입니다.
호이스팅이란 자바스크립트 코드에서 변수 또는 함수가 선언될 때, 그 선언이 마치 스코프의 최상단에서 선언되는 것처럼 동작하는 것을 말합니다. 이런 특징 덕분에 다음과 같은 코드가 문제 없이 동작하기도 하죠. add 라는 함수를 먼저 사용하고 아래에서 함수를 선언했음에도 문제 없이 3 이라는 결과를 보여줍니다. 함수의 선언이 호이스팅되어 add 보다 먼저 선언되기 때문입니다.
add(1, 2); // 3
function add(a, b) {
return a + b;
}
var 를 사용할 때 생기는 호이스팅의 문제는 var 가 변수의 선언을 스코프의 최상단으로 가져온 뒤 undefined
라는 값으로 초기화시킨다는데 있습니다. 앞서 재할당과 재선언 때문에 var 를 사용한 변수 선언이 코드의 동작에 있어서 원하지 않은 오류를 발생시키는 문제와 마찬가지로, 변수의 선언이 호이스팅되어(초기화는 호이스팅되지 않습니다) 스코프의 상단에서 선언되면서 undefined
라는 값으로 초기화되기 때문에 원하는 값이 할당되기 전까지 오류가 발생할 수 있게 됩니다.
console.log(name); // undefined
var name = "eensungkim";
console.log(name); // "eensungkim"
그러면 let, const 는 호이스팅이 되지 않는 것일까요? 그렇지는 않습니다. let 과 const 도 호이스팅됩니다. 다만 undefined
라는 값으로 초기화되지 않을 뿐이죠. 그래서 위와 같은 상황이 발생할 경우에 에러를 돌려줍니다.
이 외에도 var 는 함수 스코프로 동작합니다. let 과 const 는 블록 스코프로 동작하구요. 보통 코드는 블록을 기준으로 들여쓰기가 적용되기 때문에 우리는 블록 스코프를 기준으로 생각하게 되는데, var 는 이 점을 무시하기 때문에 또 혼란을 야기합니다.
길게 이야기했지만 해결책은 간단합니다. let, const 를 사용하는 것이죠. 이쯤 되면 왜 Dan Abramov 가 위와 같은 트윗을 작성했는지를 이해할 수 있을 것 같습니다. 개인적으로는 저도 Dan Abramov 와 같은 의견입니다.
다만 ES6 에서 let, const 가 등장했기 때문에 아직 var 를 사용하는 코드들이 남아있을 수 있다는 점에서, 또 자바스크립트가 어떻게 동작하는지에 관해 고민해볼 여지를 제공해준다는 점에서 이러한 질문에 대해 고민해보는 기회를 갖는 것은 나쁘지는 않다는 생각이 듭니다.