자바스크립트의 콜백과 비동기 처리

모모·2021년 12월 26일
0

개념 정리

목록 보기
3/3

콜백과 비동기 처리의 존재 이유

프로세스는 실행 중인 프로그램을 말하며, 데이터, 메모리 등의 리소스와 싱글/멀티 스레드로 구성되어 있다. 이때 메인 스레드에게 오래 걸리는 일(네트워크 요청, 이미지 프로세싱, 오래 걸리는 함수 실행 등)을 맡기는 것은 좋은 방법이 아니다.

따라서, 스레드의 작업을 도와줄 수 있는 "조력자"인 다른 스레드에게 오래 걸리는 일을 시킨다. 이 조력자가 일을 마치고 결과물을 스레드에게 넘겨주는 것이 "콜백"이다. 모든 일을 혼자, 순서대로 하는 대신, 스레드는 우선순위가 높은 일을, 조력자는 시간이 오래 걸리는 일을 하는 작업 방식을 "비동기 처리"라고 한다.

하지만 JavaScript는 싱글 스레드 프로그래밍 언어로서 조력자 역할을 할 다른 스레드가 존재하지 않는다. 이러한 자바스크립트의 비동기 작업을 처리하기 위해 콜백 함수나 Web API를 사용한다.

자바스크립트에서의 비동기 처리 원리

(널리 알려진 Youtube 영상 "What the heck is the event loop anyway?|Phillip Roberts|JSConfEU"를 바탕으로 정리했습니다)

들어가기 전 알아야 할 개념들

런타임
컴퓨터 과학에서 컴퓨터 프로그램이 실행되고 있는 시간, 혹은 실행되고 있는 공간을 의미한다. 자바스크립트의 런타임 환경은 크롬같은 웹 브라우저, 그리고 node.js가 있다.

자바스크립트의 런타임 환경의 네 가지 구성 요소

  • 자바스크립트 엔진: 힙 메모리, 콜 스택을 포함하는 자바스크립트 해석 엔진
    (ex. 크롬의 V8)
  • WebAPI: DOM 조작, 네트워크 요청/응답 등의 브라우저 고유 기능
  • 콜백 큐: Web API로부터 전달받은 콜백 함수를 저장
  • 이벤트 루프: 스택이 비워지면 콜백 큐에서 콜백 함수를 콜스택으로 하나씩 전달

콜 스택
데이터 스트럭처로 실행되는 순서를 기억한다.
ex) 함수를 실행하려면 스택에 해당하는 함수를 집어넣음 -> 함수에서 리턴 -> 스택의 가장 위쪽에서 해당 함수를 꺼냄

동시성
프로그램, 알고리즘 또는 문제의 다른 부분이나 단위가 최종 결과에 영향을 미치지 않고 순서가 맞지 않거나 부분적인 순서로 실행되는 능력

비동기 처리의 작동 원리

자바스크립트는 싱글 스레드 프로그래밍 언어이다.
다시 말해서,
= 한번에 하나의 싱글 콜 스택을 가진다
= 한 번에 하나의 작업을 수행한다

자바스크립트에서 함수를 호출하게 되면 콜 스택에 해당 함수가 추가된다.
해당 함수의 마지막 코드에 도달하여 return 되면 콜 스택에서 함수를 꺼낸다.

하지만 비동기적인 작업을 수반하는 코드에서는 어떻게 작동할까?

위 코드의 런타임 환경에서의 실행 순서는

    1. hi를 출력하고
    2. setTimeout을 실행하는데, setTimeout 특성상 바로 실행되지 않는다. 게다가 스택에 추가되지 않고 사라져버린다.
    3.JSConfEU를 출력한다.
    4. 5초 후 console.log('there')이 스택에 나타난다

이 과정에서 이벤트 루프(Event Loop)와 동시성(Concurrency)이 작동한다.
자바스크립트는 다른 코드를 실행시키는 동안 Ajax 요청을 실행할 수 없다. setTimeout 역시 마찬가지다.

이것을 동시에 할 수 있는 이유는 브라우저가 단순한 런타임 환경 이상의 의미를 갖기 때문이다. 자바스크립트가 구동되는 동안의 동작은 한 번에 하나만 할 수 있지만, 브라우저는 Web API같은 것들을 제공한다.

이러한 API들은 자바스크립트에서 호출할 수 있는 스레드를 효과적으로 지원한다. 여기서 동시성이 작용한다. setTimeout은 브라우저에서 제공하는 API이다. 다시 말해서, 자바스크립트가 실행되는 런타임 환경에 존재하는 별도의 API이다.

setTimeout 호출시, 브라우저의 Web API는 별도의 타이머를 실행시키고 카운트 다운을 시작한다. 즉, setTimeout 호출 자체는 완료되었다는 의미이고, 브라우저가 카운트 다운을 대신 해주기 때문에 자바스크립트 스택에서 setTimeout 함수를 지울 수 있다.

JSConfEU까지 출력을 마쳤을 때, Web API에서 자바스크립트 스택에 갑자기 함수를 집어넣을 수는 없다. 모든 Web API는 작동이 완료되면 콜백을 태스크 큐에 전달한다.

여기서 이벤트 루프가 등장한다. 이벤트 루프는 콜 스택과 태스크 큐(콜백 큐)를 주시한다. 스택이 비어있으면 큐의 첫번째 콜백을 스택에 쌓아 실행할 수 있게 해준다.

현재, 스택이 비어있고, 태스크 큐에 콜백이 하나 있기 때문에 이벤트 루프는 콜백을 스택에 넣어주고, V8 엔진으로 돌아가서 console.log('there')을 실행한다.

이것이 자바스크립트 비동기 함수가 동작하는 방식이다.

0개의 댓글