웹브라우저는 HTML, CSS, Javascript를 해석해서 화면에 그려준다.
(HTML, CSS는 브라우저의 렌더링 엔진으로, Javascript는 브라우저의 자바스크립트 엔진(ex.V8)을 사용해서 처리한다)
이때 브라우저가 자바스크립트를 읽어오는 방식때문에 비동기처리라는 특이점이 생겼다.
자바스크립트는 원래 싱글스레드 언어이다
자바스크립트 코드를 해석하고 실행하는 자바스크립트 엔진은
하나의 힙(Memory Heap)과 하나의 스택(Call Stack)을 가지고 있다.
이 요소들로 자바스크립트 코드를 어떻게 실행하는가?
1) 콜스택에 코드가 쌓인다(메모리힙에는 변수,함수 등이 저장되면서 메모리 할당이 이루어진다)
2) 스택구조 쌓인 코드들이 순차적으로 실행되기 때문에 하나의 코드가 처리된 후에 다음 코드를 처리할 수 있다.
3) 자바스크립트 엔진에는 콜 스택이 하나이므로 결국 한번에 하나의 코드만 실행 가능하다.
-> 싱글스레드 언어이며 동기식 처리를 한다.
그렇기 때문에 자바스크립트는 소요시간이 긴 연산이 들어오면 완료될때까지 다음 코드를 실행할 수 없게 된다.
* 더불어 자바스크립트 엔진에는 원래 setTimeout, DOM, AJAX 관련 메소드가 없다.
이 메소드들은 웹 앱이나 웹 사이트를 만들 때 사용할 수 있도록 브라우저가 제공하는 WebAPI이다.
이렇게 하면 누가 웹페이지에 들어오겠어
자바스크립트는 수식 연산도 가능하지만 다른 언어와 달리 웹페이지를 렌더링 하는데에 사용되는 언어이기도 하기 때문에
이렇게 싱글스레드 방식으로 비동기처리를 하면 웹구동에 문제가 생기게 된다.
실행하는데에 시간이 오래 걸리는 코드가 콜스택에 남아있어 다른 코드의 실행을 막고있다면(블로킹)
해당 코드가 종료될때까지 웹페이지에서는 흰화면만 보이거나 화면이 멈추어서 아무 반응도 할 수 없는 상태가 된다.
하지만 웹브라우저에서 자바스크립트 엔진이 구동되면 몇몇 함수들이 비동기 처리가 가능해진다.
바로 브라우저에서 제공하는 Web API관련 함수들이다.
자바스크립트 런타임(브라우저 Web APIs)
브라우저에는 Task queue 와 Event Loop가 있어서 코드의 비동기 처리가 가능하도록 돕는다.
자바스크립트엔진의 콜스택에서 Web API에 해당되는 메소드를 처리할 때가 되면
WebAPI를 호출해서 해당 코드를 비동기식으로 처리하도록 한다.
1) 콜스택에 있던 DOM 이벤트, http요청, setTimeout 등의 함수들이 WebAPI로 보내지고 콜스택에서는 다음 코드를 실행한다.
2) WebAPI가 따로 처리 되고 나면 결과값(콜백함수)가 태스크큐로 보내진다.
3) 이벤트루프는 콜스택과 콜백큐의 상태를 계속해서 확인하고 있다.
4) 콜스택에 쌓인 코드가 모두 실행되어 비어있으면 콜백큐에 대기하고 있던 함수들을 차례대로 콜스택에 올려보낸다.
WebAPI 함수들은 대부분 실행시간이 오래 걸리거나 특정 실행시점을 기다려야 하는 메소드 이기 때문에
( http요청, dom이벤트, 이벤트리스너, setTimeout 등등) 비동기함수로 처리된다.
* 브라우저의 queue에는 Task queue 외에도 Micro Task queue, Animation Frame queue가 있다.
이벤트 루프가 처리하는 우선순위는 Microtask Queue -> Animation Frames -> Task Queue 이다.
브라우저가 빠르게 돌아가도록 하려면
효율적인 처리를 위해 브라우저에서 WebAPI 호출함수를 비동기식으로 처리하게 되었지만
결국 WebAPI의 콜백함수는 자바스크립트 엔진의 콜스택이 비워져야 실행되기 때문에
웹브라우저의 동작을 최적화시키려면 코드 구성에 신경을 써야한다.
콜스택에 실행이 너무 오래 걸리는 연산을 담아두거나,
콜백함수를 과도하게 사용해서 태스크큐에 과부하를 주거나 하는 일이 없도록 신경써야한다.
오래 걸리는 코드를 써야할때 setTimeout()을 적절히 활용하거나
Worker라는 클래스를 사용해서 worker.js 파일에서 연산을 하도록 세팅하는 방법도 있다.
참고)