오늘은 비동기 프로그래밍에 대해 알아보겠습니다.
어느 평화로운날 진구와 도라에몽은 집안일을 반반 나누어서 진행하기로 했습니다.
진구는
1. 식기들 세척하기 -> 서랍장에 넣기
2. 이불, 베개 꺼내서 털기
3. 빨래 세탁기에 돌리기 -> 빨래 널기
도라에몽은
1. 바닥의 책 정리하기
2. 저녁밥 쌀 불리기 -> 밥 짓기
3. 바닥의 먼지 닦기
서로 3가지씩 일을 나눠서 진행하기로 했습니다.
그래서 이제 각각 일을 진행합니다. 진구는 빨래를 세탁기에 돌리기 시작했고, 도라에몽은 저녁밥 쌀을 불리기 시작합니다.
그런데 시작부터 진행의 차이가 생깁니다. 도라에몽은 최신기술이 탑제된 로봇답게 쌀을 불리는동안 바닥의 책 정리를 시작합니다. 쌀 불리기는 시간이 걸리는 행위이고 그동안 도라에몽은 다른 일을 할 수 있기 때문이죠.
반면 진구는 순서대로 일을 처리하겠다며 세탁기가 다 돌아갈때까지 주구장창 세탁기 앞에서 기다리고 있습니다. 역시 주인공인 이유가 있죠?
바닥의 책까지 다 정리한 도라에몽은 쌀 불리기가 끝날때까지 시간이 또 남아서 바닥의 먼지까지 닦습니다. 반면 진구는 아직도 세탁기 앞에서 기다리고 있습니다.
결국 세탁기가 다 돌아가고 진구는 이제 빨래를 널기 시작합니다. 도라에몽도 쌀짓기가 끝나 밥을 짓기 시작하죠. 둘 다 작업이 끝나기까지 기다렸지만, 진구는 할 일이 아직 많이 남았고, 도라에몽은 할일을 다 처리했습니다.
여기서 진구처럼 일하는 것은 동기적, 도라에몽처럼 일하는 것은 비동기적 이라고 볼 수 있습니다. 쉽게 말하면 어떤 작업이 완료되는동안 다른 작업을 진행할지 말지에 대한 얘기입니다.
어렵지 않죠? 동기와 비동기는 개념적으론 이런 차이를 가지고 있습니다. 여기서 알람을 맞추기 위해 콜백함수를 사용하고, 이벤트라는 개념을 사용할 뿐이죠. 두 개념을 이미 어느정도 알고 있다면 이번 포스팅은 더욱 쉽게 받아들일 수 있을 겁니다.
비동기를 사용하면 효율적인 작업이 가능하다는 사실을 살펴봤습니다. 코드의 순서가 조금 복잡해 보이지만 다른 작업의 처리를 기다리지 않고 계속해서 다른 작업을 수행할 수 있다는 장점이 있죠.
그렇다면 자바스크립트에서 이러한 비동기를 어떻게 구현하고 있는지 살펴보겠습니다.
자바스크립트의 비동기 프로그래밍을 이해하기 위해 필요한 구조는 위와 같습니다. 하나하나 구체적으로 살펴보겠습니다.
먼저 가장 중요한 콜스텍이 있습니다. 실행 컨텍스트에 대한 포스팅 기억하시죠? 자바스크립트의 실행 컨텍스트들이 담기는 콜스텍입니다. 작업 처리소라고 보시면 편리합니다.
다음으로 Web API라는 영역입니다. 자바스크립트는 브라우저(또는 node)위에서 동작하도록 되어있습니다. 그리고 브라우저에는 멀티 스레드로 이용 가능한 Web API라는 영역이 존재하죠. 이곳은 다른 곳에 request를 날리는 등의 작업을 처리해주는 역할을 합니다. 쉽게 보자면 비동기 명령을 실제로 처리하는 영역이라고 할 수 있습니다.
세 번째로 Task Queue, 대기큐입니다. 이곳에는 비동기 명령을 마친 작업들의 콜백함수가 담기게 됩니다.
마지막으로 이벤트 루프입니다. 콜스텍과 테스크 큐를 계속 확인하며 콜백 함수를 실행시켜 주는 구조입니다.
자, 이제 실제 비동기 작업이 들어오면 어떻게 수행되는지 확인해보겠습니다.
먼저 작업이 들어오면 콜스텍에 쌓이게 됩니다.
그러다 비동기 작업이 콜스텍에 들어오게 됩니다.
이러한 비동기 작업은 Web API와 같은 담당 영역으로 들어가 처리를 기다립니다. (Web API는 자바스크립트와 독립적으로 돌아가는 멀티 스레드 환경이라고 이해하시면 좋습니다.)자 이제 자바스크립트는 자바스크립트대로 콜스텍의 작업들을 처리합니다. Web API도 비동기 명령을 처리하고 응답을 기다리겠죠?
이렇게 서로 독립적인 작업을 수행하다가 Web API에서 처리하던 비동기 작업이 완료됩니다.작업이 완료되면 결과와 함께 콜백함수가 Task Queue에 들어가게 됩니다. 이제 비동기 작업이 완료되었으니, 그 결과에 따라 콜백함수가 적절하게 처리되면 되겠죠?
여기서 이벤트 루프의 역할이 나옵니다. 이벤트 루프의 일반적인 구현은 다음과 같습니다. (출처 - https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop)
쉽게 보면 동기적으로 이벤트 Task Queue를 감시하고 있다고 생각하시면 되겠습니다.
이렇게 이벤트큐는 Task Queue와 콜스텍을 계속해서 감시합니다.
그러다 자바스크립트의 콜스텍이 비워지게 되면?이제 이벤트루프는 대기하고 있던 콜백 함수를 콜스텍에 올려놓습니다. 이제 이 콜백함수는 자바스크립트 스레드에 의해 처리되고, 그 결과가 우리(개발자)에게 보여지게 됩니다.
싱글 스레드(콜스택 하나)인 자바스크립트에서 비동기작업을 처리하기 위해선, 필연적으로 이와 같은 구조가 만들어지게 되었다고 생각합니다. 이는 콜백함수와 이벤트에 대한 이해가 필수가 되겠죠.
비동기처리를 공부하며 이벤트 루프, 테스크 큐 등이 구체적으로 어떻게 구현되어 있는지, 더 나아가 이벤트 드리븐 방식의 개발에서 이벤트들이 어떠한 자료구조로 관리되고 있는지 등을 살펴보시면 자바스크립트의 올바른 이해에 도움이 될 것이라 생각합니다.