위와 같은 작업을 자바스크립트로 하고 싶다고 해보죠. 그러면 일단 다음과 같은 코드를 생각할 수 있습니다.
console.log(1+1);
setTimeout(function(){}, 1000);
console.log(2+2);
이렇게 실행을 하면 될까요? 결론은 안된다는 것입니다. 1초 쉬는거 없이 그냥 바로 2, 4가 출력되는 것을 확인할 수 있을 것입니다. 그 이유는 setTimeout함수 사용법이 약간 잘못되어서 그렇습니다. 일단 고치려면 다음과 같이 쳐야합니다.
console.log(1+1);
setTimeout(function(){ console.log(2+2) }, 1000);
그럼 1+1 하고 1초쉬고 2+2하고 바로 3+3을 출력하고 싶어서 다음과 같이 치면 어떻게 될까요?
console.log(1+1);
setTimeout(function(){console.log(2+2)}, 1000);
console.log(3+3);
결과는 다음과 같습니다.
✅ 2원하는 순서대로 나오지 않습니다. 자바스크립트가 다른 프로그래밍 언어와 다른점이 있기 때문입니다. 대충 지금까지 실행 결과로 미루어 보아, 자바스크립트는 뭔가 처리가 빠른것부터 먼저 처리하는 경향이 있어 보입니다. 그럼 병렬처리가 가능한 언어란 말인가요? 그건 아닙니다. 자바스크립트는 브라우저에서 읽는 언어이입니다. 따라서 브라우저의 동작 원리를 알면 왜 이런 실행 방식을 가지는지 이해할 수 있습니다.
웹 브라우저는 쉽게 말해 자바스크립트 코드를 해석하고 실행해주는 엔진입니다. 웹 브라우저의 자바스크립트 해석 단계를 알아보겠습니다.
우선 브라우저에는 스택이라는 공간이 있습니다. 브라우저가 이 스택에 우리가 작성한 코드를 차례로 push하고, 실행시킨 후 pop합니다. 도중에 변수 선언같은게 있으면 heap이라는 공간에 보관하게 됩니다. 스택은 하나만 있습니다. 즉, 한번에 코드 하나만 실행할 수 있다는 얘기입니다. 그래서 자바스크립트를 single-threaded language라고 부릅니다. 병렬처리를 할 수 없다는 뜻입니다.
스택에서 코드를 하나씩 실행시킬 때, setTimeout과 같이 당장 실행을 시킬 수 없는 코드들은 스택에 넣지 않고 대기실같은 공간으로 제껴놓고 바로 다음 코드를 실행시킵니다.
이런 대기실로 보내는 코드들은 정해져있습니다. Ajax요청, eventListener, setTimeout등이 있습니다. 이렇게 대기실에 보내진 코드들은 실행할 때가 오면 다시 스택으로 옮겨지고 실행됩니다. 그런데 이렇게 실행할 때가 온 코드들도 대기실로 먼저 보내진 후에 차례로 스택으로 옮겨집니다. 이 대기실의 대기실은 큐 자료구조로 되어있습니다. 그래서 먼저 들어온 코드들이 먼저 스택으로 옮겨지고 실행됩니다.
여기서 가장 중요한 조건이 있는데, 바로 큐에서 스택으로 코드를 차례로 옮기는 과정에서,
✅ **스택이 비어있을 때만 옮긴다는 조건입니다.**이런 브라우저의 자바스크립트 실행 원리를 알고 나면, 자바스크립트에서 시간이 오래걸리는 (가령 천만번 이상의 반복문이나, 어려운 수학적인 계산 등)코드는 쓰면 안된다는 것을 알 수 있을 겁니다. 왜냐면, 어떤 버튼을 누르면 모달창 띄워즈는 코드가 있고, 1억번 반복문 돌리는 코드가 있다고 생각해보죠. 버튼 모달 코드는 버튼이 언제 눌려질 지 모르기 때문에 스택으로 안가고 대기실로 갈 것입니다. 그런데 1억번 반복문 코드는 스택에서 바로 실행을 시킵니다. 10초가 걸리는 연산이라고 가정하면, 그 10초안에 버튼을 누가 누른다면 모달은 띄워지지 않을 것입니다. 왜냐하면 대기실에 있는 코드는 큐를 거쳐서 스택으로 이동하는데, 스택이 비어있을 때만 이동이 가능하기 때문에, 저 반복문이 끝나기 전까지는 스택으로 이동해서 실행시킬 수 없으니까요. 그래서 브라우저 응답이 없습니다 와 같은 렉이 걸리게 됩니다.
교훈을 정리하자면 다음과 같습니다.
자바스크립트의 실행 특성
천잰가요?