

요즘은 JS스터디에서 혼자 공부하는 자바스크립트 책을 같이 보고있습니다. 보통 자바스크립트의 교과서라고 불리는 딥다이브와 같은책보다는 양도적고 깊이도 낮은편이지만 저는 항상 어떤 것에 흥미를 가지려면 쉽게 쉽게 시작해야하는 경향이 있어서 이책으로 쭉 읽어보고 있습니다. 오늘은 그중에서 헷갈리고 흥미로운 내용인 호이스팅에 대해서 알아보려고 합니다
제가 일전의 커리어리 라는 어플에서 호이스팅 관련 글을 읽은적이 있습니다. 글의 내용인 즉슨, 프론트엔드 신입 지원자가 면접을 봤는데, "호이스팅이 뭐냐"라는 질문에 함수나 변수가 위로 끌어올려지는 기능 이라고 대답을 했다고 합니다. 그러고나서 면접관으로부터 지속적으로 꼬리물기 질문이 들어오면서 공격을 받았다고 합니다.
저또한 호이스팅을 저렇게 이해하고 있었습니다. 처음 배울때 단순하게 그런식으로 이해했기 때문이죠.
mdn 공식문서 에 따르면 호이스팅의 정의를 JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables or classes to the top of their scope, prior to execution of the code. 라고 하고있습니다. 이 정의를 읽어본다면 "위로 끌어올려진다"는 표현은 얼핏 맞는것 같기도 합니다. 그러나, "whereby the interpreter appears to move" 라는 구문을 보면 알 수 있듯이, 그게 실제로 올려지는것이 아니라 그렇게 "보이는"것일 뿐입니다.
그럼어떻게 변수와 함수 선언이전에 사용을 할 수 있을까요? 실행 컨텍스트가 생성될때 variable배열에 변수들을 먼저 담아 둡니다. 그렇기 때문에 선언을 나중에 해도 사용이 가능한 것이죠.
console.log(a); //undefined
var a = 4;
console.log(a); //4
위와 같은 구문을 실행시키면 어떻게 될까요? 우선 var변수의 호이스팅은 명백하기 때문에 undefined와 4가 나오는것을 알 수 있습니다. a가 선언이 되지않았지만 호이스팅에의해 undefined로 변수가 초기화되어있는것이죠.
console.log(a);
const a = 4;
console.log(a);
그러면 위의 구문은 어떨까요? 당연히, 2번째 3번째 줄까지 가지도 못하고 오류를 발생시킵니다.

어? 저희는 여기서 또 이상한 점을 눈치채야 합니다. 변수선언이 안되어있으면, 'a' is not defined와 같은 오류가 나야할텐데, 그것이 아니라 a를 초기화전에는 사용할수없다고 합니다. 여기서 알 수 있는점은, const변수를 사용했음에도 'a'라는 변수 선언자체는 호이스팅이 되었다는 것이죠.
확인해보겠습니다.
console.log(a);
이구문은 당연히

정의가 안되었다가 나옵니다.
따라서 const, var, let은 모두 선언이 호이스팅 되는것이 맞습니다. 단지, const, let은 set_initializer_position이라는 메모리 할당 이전의 방어 코드가 추가됨으로써, 메모리에 직접적으로 할당이 되어있는것은 아닌것이죠.
저는 그래서 JS를 처음 배우면서 굉장히 힘들어하고있습니다. 이 함수들이 완전히 동일한것도 아니고 약간의 차이가 있기 때문입니다. 그래서 저는 일단은 처음 배우는 입장에서 약간의 규칙을 정해두었습니다.
콜백함수로쓰는것은 화살표함수를
함수선언식과 함수표현식중에서는 함수표현식을
쓰기로 저만의 약속을 정했습니다.
왜 제가 함수선언식대신 함수표현식을 쓰기로 약속을했을까요??
바로 함수호이스팅때문입니다.
결론부터 말하자면 함수 표현식(익명함수)는 호이스팅이 되지않고, 함수 선언식은 호이스팅이 됩니다.
물론 편하고 각자 자신의 소속에 맞는 컨벤션에 맞춰서 선택해서 사용하면 되지만... 최근에는 많은 개발자가 코드 안전상의 이유로 함수표현식을 사용하는 추세라고 합니다(물론 호이스팅을 선호해서 일부러 선언식을 사용하는 사람들도 있습니다). 그러면 왜 함수표현식이 더 안전할까요??
test = function () {
console.log("함수 표현식입니다");
};
function test() {
console.log("함수 선언식입니다.");
}
test();
위와 같은 함수구문의 결과는 어떻게 나올까요? 이론상 두번째 함수 선언문이 뒤에나왔기때문에 앞의 표현식을 덮어씌워서 결과가 함수 선언식입니다가 나올것 같지만...

결과는 함수 표현식이 나왔습니다. 이유는 저희가 모두 알고있습니다. 함수선언식이 호이스팅되어 같은 블록 scope의 상단에서 선언이 되기 때문이죠. 따라서 함수선언식을 함수 표현식이 덮어씌워버리는 상황이 발생합니다.
이것이 뭐가 문제일까요? 단순하게 생각하면 저희가 짜는 코드는 항상 위에서 아래로 로직을 갖추면서 코드를 구성합니다. 그러나, 호이스팅이 개입되게 되면 그 순서와 관계없이 코드가 실행되기 때문에 굉장히 위험하게 됩니다. 따라서 되도록이면 함수표현식을 사용하기로 저는 스스로 규칙을 정하려고 합니다.
let test = function () {
console.log("함수 표현식입니다");
};
function test() {
console.log("함수 선언식입니다.");
}
test();
또한, 함수를 선언할때(함수표현식) 과거의 var가 아닌, let과 const를 사용해준다면 자바스크립트에서 오류를 발생시키므로 호이스팅으로 인한 위험요소를 미연에 방지할수도있습니다.
