본문 바로가기
이론/Frontend

싱글 쓰레드 Javascript의 비동기적 동작

by 유세지 2020. 9. 7.

Javascript

 

이 글은 JSConf EU 2014에서 발표 된 Philip Roberts의 What the heck is the event loop anyway? 의 내용을 듣고 정리한 글입니다.

 

 

동기와 비동기는 프로그래밍을 하는 사람이라면 한 번쯤은 들어봤을법한 단어들입니다.

간단히 말하면 동기는 태스크(task)를 순차적으로 실행하는 것 이고, 비동기는 병렬적으로 처리하는 것 입니다.

 

이러한 동기의 가장 큰 문제점이 바로 하나의 태스크가 완료되기 전까진 다른 일을 수행할 수 없고, 끝날때까지 기다려야 한다는 점입니다. 우리가 사용하는 모든 프로그램이 동기적인 동작밖에 취할 수 없다면 큰 문제가 발생하겠죠.

 

이는 웹에서도 마찬가지입니다.

 

우리는 웹에서 수 많은 동작들을 실행합니다. 이곳저곳에서 데이터들을 받아오고, 때로는 조작하는 일련의 과정들이 모두 동기적으로 이루어진다면 상당히 곤란할 것입니다. 예를 들어 네이버 메인 화면을 띄운다고 생각해봅시다.

네이버의 메인 화면에서는 광고도 받아와야 하고, 인기 검색어 순위도 받아와야 하고, 뉴스기사들도 받아와야합니다. 그런데 이 모든 과정이 하나하나 순차적으로 이루어져야만 한다면 어떻게 될까요?

 

광고나 검색어 순위를 받아오는 과정에서 뭔가 문제가 발생해 연결이 되지 않기라도 한다면 Timeout이 될때까지 기다려야 할 것이고, 이는 사용자에게 큰 짜증을 불러 일으킬 것입니다.

 

동기와 비동기에 대한 자세한 내용은 동기와 비동기 (Synchronous & Asynchronous)를 참고해주세요.

이 포스팅에서는 우선 어떻게 자바스크립트에서 비동기적인 동작을 수행할 수 있는지에 대해 알아보겠습니다.

 

 

 

# 자바스크립트 = 싱글 쓰레드

 

우선 자바스크립트는 싱글 쓰레드입니다.

 

쓰레드는 프로세스 내에서 실행되는 흐름의 단위를 말하는데, 자바스크립트 엔진(V8)은 이 쓰레드가 하나밖에 존재하지 않기 때문에 기본적으로 동기적인 동작밖에 할 수 없습니다.

 

하지만 우리는 오랜 경험으로 웹에서 수 없이 많은 동작들이 비동기적으로 수행된다는 것을 알고 있습니다.

어떻게 이런 일이 가능할까요?

 

이것을 이해하기 위해서는 자바스크립트의 실행 환경에 대해 생각해봐야합니다.

 

모든 프로그램이 그렇듯 프로그래밍 언어가 단순한 문자의 나열이 아닌, 나름의 규칙을 가진 코드로서 동작하려면 그에 맞는 실행 환경이 필요합니다. 이를 런타임이라고 부릅니다.

 

자바스크립트 또한 마찬가지로 실행 환경 위에서만 동작할 수 있고, 이는 우리가 실생활에서 아주 흔하게 접하고 있습니다. 그것은 바로 지금 이 글을 보고 계신 여러분께서도 마주하고 있는 브라우저입니다.

 

 

구글의 대표적인 브라우저, Chrome입니다.

 

 

 

브라우저는 그 자체로 자바스크립트를 실행할 수 있는 런타임이라고 할 수 있습니다. 이 브라우저가 없이는 자바스크립트는 그저 문자들의 나열에 불과하며, 어떤 동작도 할 수 없게 됩니다. 혹여 또 다른 런타임인 Node.js 등이 있지 않은 이상 말이죠.

 

노드나 브라우저와 같은 런타임은 작성된 자바스크립트 코드를 읽고, 의도된 동작을 보여주거나 수행하게 됩니다.

 

자바스크립트가 비동기적 동작을 하는데 왜 뜬금없이 브라우저나 노드같은 런타임이 나오는지 의아해 하실 수도 있는데, 이 부분을 짚고 넘어가지 않을 수 없었습니다.

 

바로 이 런타임이 멀티 쓰레드를 제공하기 때문입니다.

 

 

# 멀티 쓰레드를 제공하는 브라우저

 

브라우저, 즉 런타임이 멀티 쓰레드를 제공하기 때문에 비로소 자바스크립트는 이 위에서 비동기적인 동작들을 수행할 수 있게 됩니다. 조금 더 자세히 살펴보겠습니다.

 

아래 그림은 자바스크립트가 실행되는 과정을 간단히 나타낸 그림입니다.

 

1) 자바스크립트 코드 부분에서 테스크를 콜스택(편의상 스택으로 부르겠습니다)으로 보냅니다.

2) 비동기적으로 처리해야하는 테스크가 들어올 경우, Web APIs 부분으로 보내집니다.

3) Web APIs 부분에서 처리된 테스크는 콜백큐(편의상 로 부르겠습니다)로 보내집니다.

4) 이벤트 루프는 스택에 있던 테스크들이 모두 팝된것을 확인하고, 콜백큐의 테스크를 스택으로 보냅니다.

 

 

브라우저에 내장되어있는 Web APIs는 비동기적인 동작에 필요한 함수들을 처리하는 역할을 합니다.

좀 더 정확히 말하면 우리가 흔히 사용하던 setTimeout, Ajax 등등의 함수는 자바스크립트 엔진 내부가 아닌, 브라우저에 포함된 Web APIs에 내장되어있다고 생각하시면 될 것 같습니다.

 

실제로 자바스크립트 엔진을 아무리 뜯어봐도 setTimeout 같은 함수는 찾아볼 수 없습니다. 그 이유가 바로 여기에 있었네요.

 

setTimeout은 web API인 WindowTimer에 명시되어 있었습니다. (출처: MDN web docs)

 

 

지금까지 나온 내용들을 정리하면 이렇습니다.

 

- 비동기적인 동작을 하는 함수들은 자바스크립트 내장 함수가 아니고, web APIs에서 찾아볼 수 있다.

- 싱글 쓰레드인 자바스크립트 엔진이 멀티 쓰레드 동작을 할 수 있는 것은 브라우저(런타임) 덕분.

 

가끔 setTimeout 등의 함수가 의도치 않은 순서로 동작했었는데, 아마 높은 확률로 콜스택에 이미 다른 테스크가 들어있었던게 아닐까 하는 생각이 듭니다.

 

우연찮게 접한 발표 영상의 내용이 흥미로워서 간단하게나마 정리해보았습니다. 그동안 몰랐던 브라우저의 동작 방식을 조금이나마 알게 된 것 같습니다.

 

이 글을 읽는 여러분께도 도움이 되셨으면 좋겠습니다.

잘못 정리한 내용은 언제든 덧글로 지적해주시면 감사하겠습니다!

 

마지막으로, Philip Roberts의 발표 스크립트 전문은 이곳에서 확인하실 수 있습니다.

 

반응형

댓글