코딩애플님의 개발자 90% 모르는 JS 동작원리 강의를 듣고 정리해보았다.
강의 링크
브라우저에서의 JS 동작원리
console.log(1 + 1)
setTimeout(function () {
console.log(2 + 2)
}, 1000)
console.log(3 + 3)다음과 같은 코드를 실행해보면, 2와 6이 바로 출력되고 1초 후에 4가 출력된다. 이는 비동기로 동작하는 setTimeout 함수 때문이다.
웹 브라우저는 자바스크립트를 실행시켜주는 엔진이라고 볼 수 있다. 브라우저가 코드를 해석해서 그걸 동작시켜준다.
웹 브라우저의 내부를 보면 Stack, Heap, 그리고 Queue 가 존재한다.
Stack에 JS 코드 한줄 한줄을 넣어주고, 차례대로 실행시켜준다. 코드 실행을 할 때, 변수를 만나면 Heap에 저장된 변수를 참조한다.
Stack은 브라우저 내에서 하나만 존재하므로, JS는 싱글스레드 언어라고한다. setTimeout과 같은 코드는 실행되는데 오래걸리므로, 대기실에 잠시 넣어준다. Stack은 원래 바쁜 녀석이라 대기실이 필요하다. Ajax 요청코드, setTimeout, 이벤트 리스터와 같은 코드들이 대기실에 들어가게 된다.
시간이 지난 후, 처리가 완료된 오래 걸리는 코드들은 Queue에 들어가게 된다. Queue에 있는 코드들을 하나씩 Stack 으로 옮겨주는 데, 이를 Event Loop 라고 한다. 단, Stack이 비어있을 때만 옮겨준다.
만약, setTimeout 에 0초를 주면 어떻게 될까?
setTimeout 같은 녀석들을 Stack에서 무조건 대기실로 보내버린다.
만약, for문에서 10초정도 걸리는 매우 어려운 연산을 한다고 가정해보자. Stack에서 10초동안 이 연산을 수행하는 와중, 대기실에는 버튼 클릭하면 모달이 뜨는 코드가 있다. 그런데, 이 코드는 0초만에 실행되어야 하는데, Stack이 10초동안 바쁘기 때문에, 대기실에 있는 코드들은 10초동안 기다려야 한다. Queue에서 Stack으로 옮겨지는 것은 Stack이 비어있을 때만 가능하기 때문에 모달창이 뜨지 않는다. 버튼을 누르면 응답 없는 페이지와 같은 메세지가 뜬다.
따라서, stack과 queue를 바쁘게 하면 안된다.
for문에 너무 어려운 연산을 넣는다거나, 버튼에 eventListener를 1000개 달아놓으면 안된다.
동기적 VS 비동기적
JS는 원래 동기적이다. 한번에 한줄 순서대로 실행이 된다. Stack은 하나기 때문이다.
하지만, setTimeout, 이벤트리스너, ajax 함수 등을 쓰면 비동기적으로 동작한다고 이해하면 된다. 잠시 대기실에 코드를 뺀 다음, 처리가 완료되면 다시 Queue에 넣어놓기 때문이다.
