먼저, 자바스크립트 동작원리가 궁금해진건 내가 개념이 부족하다는 생각이 들어서이다.
물론 공부를 하면서 대충은 이해를 하고있었다. 하지만 암기한다는 느낌으로
JS는 싱글스레드이면서, 논블로킹 언어이다. 싱글스레드 이기때문에 비동기 요청이 필수이다.
해당 내용들에 대한 이해는 모두했다. 흔히 예시로 설명하는 카페종업원, 식당직원 등의 이야기보다는 게임을 좋아하는 나에게 맞춘 예시로, 같은 시간에 핸드폰게임 자동사냥을 돌려놓고, 컴퓨터로는 블록체인을 채굴하며 온라인 게임을 한다.
뭐 이런느낌이지 않을까 싶다.
하지만 이런 예시들만으로는 부족하다는 생각이 문득 들었다.
만약 일을 하면서 오류가 발생했을 때, 과연 내가 원인파악을 잘 할 수 있을까를 계속 고민하다보니 그냥 대충 돌아가는 프로세스만을 이해한다기 보다는, 원인과 근거를 포함한 자바스크립트의 동작원리를 잘 알고있어야 겠구나 싶었다.
자바스크립트의 큰 특징 중 하나는 '단일 스레드' 기반의 언어라는 점이다. 스레드가 하나라는 말은 곧, 동시에 하나의 작업만을 처리할 수 있다라는 말이다. 하지만 실제로 자바스크립트가 사용되는 환경을 생각해보면 많은 작업이 동시에 처리되고 있는 걸 볼 수 있다. 예를 들면, 웹브라우저는 애니메이션 효과를 보여주면서 마우스 입력을 받아서 처리하고, Node.js기반의 웹서버에서는 동시에 여러 개의 HTTP 요청을 처리하기도 한다. '자바스크립트는 하나의 스레드를 이용해서 어떻게 동시성 작업을 처리할까?'
만일 싱글 스레드로 브라우저 동작이 한번에 하나씩 수행하게 되면, 우리가 파일을 다운로드 받을 동안 브라우저는 파일을 다 받을 때까지 웹서핑도 못하고 멈춰 대기해야 할 것이다. 따라서 파일 다운, 네트워크 요청, 타이머, 애니메이션 이러한 오래 걸리고 반복적인 작업들은 자바스크립트 엔진이 아닌 브라우저 내부의 멀티 스레드인 Web APIs에서 비동기 + 논블로킹으로 처리된다. 비동기 + 논블로킹
(Async + Non blocking)Visit Website는 메인 스레드가 작업을 다른 곳에 요청하여 대신 실행하고, 그 작업이 완료되면 이벤트나 콜백 함수를 받아 결과를 실행하는 방식을 말한다. (쉽게 말해 파일 다운로드 요청 작업을 백그라운드 작업으로 전이하여 동시에 처리가 가능하도록 한 것으로 이해하면 된다)
즉, 비동기로 동작하는 핵심요소는 자바스크립트 언어가 아니라 브라우저라는 소프트웨어가
가지고 있다고 보면 된다. Node.js 에서는 libuv 내장 라이브러리가 처리한다.

싱글 스레드인 자바스크립트의 작업을 멀티스레드로 돌려 작업을 동시에 처리시키게 하던가, 또는 여러 작업 중 어떤 작업을 우선으로 동작시킬 것인지 결정하는 세심한 컨트롤을 하기 위해 존재하는 것이 바로 이벤트 루프(Event Loop) 이다. 이벤트 루프는 브라우저 내부의 Call Stack, Callback Queue, Web APIs 등의 요소들을 모니터링하면서 비동기적으로 실행되는 작업들을 관리하고, 이를 순서대로 처리하여 프로그램의 실행 흐름을 제어하는 녀석이다.
간단히 표현하자면 브라우저의 동작 타이밍을 제어하는 관리자라고 보면 된다. 이벤트 루프의 동작 과정을 간단히 살펴보자면, 자바스크립트의 setTimeout이나 fetch 와 같은 비동기 자바스크립트 코드를 브라우저 Web APIs에게 맡기고, 백그라운드 작업이 끝난 결과를 콜백 함수 형태로 큐(Callback Queue)에 넣고 처리 준비가 되면 호출 스택(Call Stack)에 넣어 마무리 작업을 진행한다.
이러한 이벤트 루프를 이용한 프로그램 방식을 이벤트 기반(Event Driven) 프로그래밍이라고 하는데, 이벤트 기반 프로그래밍은 으로 비동기 작업을 쉽게 처리할 수 있고, 멀티 스레드 언어에 비해 단순하고 직관적인 코드 작성을 가능하게 하며, 브라우저와 같은 환경에서도 안정적인 실행을 가능하게 하여 사용자와의 상호작용을 높일 수 있다. 따라서 이를 이해하고 적절한 방식으로 비동기 작업을 처리하는 것은, 자바스크립트를 이용한 웹 애플리케이션 개발에 있어서 매우 중요하다.
Call Stack : 자바스크립트 엔진이 코드 실행을 위해 사용하는 메모리 구조
Heap : 동적으로 생성된 자바스크립트 객체가 저장되는 공간
Web APIs: 브라우저에서 제공하는 API 모음으로, 비동기적으로 실행되는 작업들을 전담하여 처리한다. (AJAX 호출, 타이머 함수, DOM 조작 등)
Callback Queue : 비동기적 작업이 완료되면 실행되는 함수들이 대기하는 공간
Event Loop : 비동기 함수들을 적절한 시점에 실행시키는 관리자
Event Table: 특정 이벤트(timeout, click, mouse 등)가 발생했을 때 어떤 callback 함수가 호출되야 하는지를 알고 있는 자료구조

DOM : HTML 문서의 구조와 내용을 표현하고 조작할 수 있는 객체
XMLHttpRequest: 서버와 비동기적으로 데이터를 교환할 수 있는 객체. AJAX기술의 핵심.
Timer API: 일정한 시간 간격으로 함수를 실행하거나 지연시키는 메소드들을 제공
Console API : 개발자 도구에서 콘솔 기능을 제공
*위 항목들을 제외하고도, webAPI의 종류가 더 많습니다.
Web APIs는 타이머, 네트워크 요청, 이벤트 처리 등 브라우저에서 제공하는 다양한 API를 포괄하는 총칭이다. Web API는 브라우저(Chrome)에서 멀티 스레드로 구현되어 있다. 그래서 브라우저는 비동기 작업에 대해 메인 스레드를 차단하지 않고 다른 스레드를 사용하여 동시에 처리할수 있는 것이다.
예를 들어, setTimeout 비동기 작업은 Web APIs의 한 종류인 Timer API 에서 타이머 스레드를 사용하여 타이머를 수행한다. 마찬가지로, XMLHttpRequest , fetch와 같은 네트워크 관련 API는 네트워크 스레드를 사용하여 네트워크 요청과 응답을 처리된다.
이 때, 모든 WebAPI 들이 비동기로 처리된다고 착각하면 안된다. Web API에는 동기적으로 처리되는 것과 비동기적으로 처리되는 것이 모두 있다. 예를 들어 DOM API나 Console API는 동기적으로 처리되고, XMLHttpRequest나 Timer API는 비동기적으로 처리된다.
Web APIs가 여러 API들을 묶어 말하듯이, Callback Queue도 여러가지 종류의 Queue를 묶어 총칭하는 개념이다. Callback Queue에는 (macro)task queue와 microtask queue 두 가지 종류가 있다.

Callback Queue의 종류에 따라 이벤트 루프가 콜 스택으로 옮기는 순서가 달라진다. 일반적으로 microtask queue가 가장 우선순위가 높아 먼저 microtask queue를 처리하여 먼저 비우고 그라음 task queue의 콜백을 처리한다.
앞의 내용을 복습하자면, 싱글 스레드인 자바스크립트에서도 작업의 동시 처리을 지원할 수 있는 비결에는 이벤트 루프가 자바스크립트 엔진과 브라우저의 웹 API를 연결하여 비동기적인 일 처리를 가능케 하기 때문이다. 다만 모든 자바스크립트 코드를 비동기로 처리할 수 있는 것은 아니다. 자바스크립트에는 비동기로 동작하는 비동기 전용 함수가 있는데 대표적으로 setTimeout 이나 fetch, addEventListener 가 있다.

브라우저의 Web APIs는 위 그림과 같이 각각 전용 작업을 처리하는 API 스레드들로 구성된 집합을 말한다. 따라서 setTimeout 이 호출되면 Timer API 라는 별도의 스레드에서 타이머 동작이 별도로 실행되는 것이며, fetch 가 호출되면 Ajax API 스레드에서 네트워크 통신이 이루어 지는 것이다.
이벤트 루프(Event Loop)는 이 비동기 함수 작업을 Web API에 옮기는 역할을 하고 작업이 완료되면 콜백을 큐(Queue)에 적재했다가 다시 자바스크립트 엔진에 적재해 수행시키는 일종의 '작업을 옮기는 역할' 만을 한다. 작업을 처리하는 주체는 자바스크립트 엔진과 웹 API 이다. 그래서 이벤트 루프는 Call Stack에 현재 실행 중인 작업이 있는지 그리고 Task Queue에 대기 중인 작업이 있는지 반복적으로 확인하는 일종의 무한 루프만을 돌고, 대기 작업이 있다면 작업을 옮겨주는 형태로 동작한다고 보면 된다. (그래서 이벤트 '루프' 이다)
setTimeOut(), async() => await , fetch등 비동기 메서드마다 동작방식이 다르다고한다.
다 이해했다고 생각하고 넘어갔던 것들이 사실은 그렇지않다는거.. 아직 배울게 너무 많다
하지만 이런 기초적인 것 부터 이해하고 있어야 js를 이용한 코드를 작성할 때,
좀 더 이해도를 갖고 효율적인 코드를 작성할 수 있을 것 같다.
대충 돌아가는 로직만 알면 된다라는 생각은 이제 안할것 같다.
사실 나같은 초보개발자가 해당내용을 이해한다고 해서 퍼포먼스가 바로 폭팔적으로 올라가진 않을거지만, 이런게 쌓이고 쌓이다 보면 생각하는 방식이 지금과는 크게 달라질거라 생각함.
이번 내용을 공부하니 DOM의 동작과정도 한번 자세히 알아보고싶다는 생각이 든다.
https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif
위 링크에 JS EventLoop를 동적인 애니메이션 예시를 통해 자세히 설명해준다.
해당 글을 보면 이해하는데 훨씬 도움이 될 것이다.