비동기처리는 무엇인가?

개발을 하다 보면 의도적으로 해당하는 코드를 후에 실행 시키고 싶을 때가 있다. 이때 사용하는 것이 바로 비동기 함수다. 비동기 함수는 특정 코드의 실행이 끝난 후 호출되는 콜백 함수를 등록하는 방식으로 동작한다. 비동기 함수는 자바스크립트에서 가장 많이 사용되는 함수 중 하나이다.

하지만 이 비동기 함수를 적용시키다 보면 내가 의도하지 않았던 방향으로 작동하게 되는 경우가 있다. 이를 이해 하기 위해서는 비동기 함수의 동작 방식을 이해해야 한다.

비동기 함수의 동작 방식

먼저는 사실 비동기 함수의 대표격인 setTimeout 은 사실 기본적으로 자바스크립트에 내장되어 있는 기능이 아니다. 바로 브라우저에서 제공하는 기능이다. Dom API 가 브라우저에서 지원하는 기능이기 때문에 node 환경에서는 작동하지 않는다.

그렇다면 제대로 비동기 함수를 이해 하려면 반드시 브라우저의 기본적인 자바스크립트 엔진의 동작 방식을 알고 있어야 한다. 브라우저의 자바스크립트 엔진은 Single Thread 방식으로 동작한다. 즉, 한 번에 하나의 코드만 실행할 수 있다. 그렇다면 비동기 함수는 어떻게 동작할까?

console.log('1');
setTimeout(() => {
  console.log('2');
}, 0);
console.log('3');

위 코드를 실행하면 어떤 결과가 나올까? 1, 3, 2 가 나올 것이다. 이는 setTimeout 의 콜백 함수가 0 초 후에 실행되는 것이 아니라 setTimeout 이 실행되자 마자 바로 실행되는 것이다. 그렇다면 setTimeout 은 왜 0 초 후에 실행되는 것처럼 보일까?

그 이유는 아래의 사진에서 볼 수 있다.

먼저 callStack 의 작동방식은 먼저 들어온 요청이 나중에 실행되며 제일 마지막에 들어온 요청을 실행한다. 그리고 나서 webapi 에서 해당하는 이벤트를 처리한 후에 밑에 있는 callback Queue 에 콜백 함수를 넣는다. 그리고 callStack 이 비어있을 때 callback Queue 에 있는 콜백 함수를 callStack 에 넣어 실행한다.

위와 같은 일련의 과정 덕분에 setTimeout 의 콜백 함수가 0 초 후에 실행되는 것처럼 보인다. 하지만 뒤에 있는 0 은 사실 해당하는 초 뒤에 함수를 실행을 반드시 해주는 것이 아니라 webapi 에서 해당하는 이벤트를 처리할 수 있는 시간이다. 그렇기 때문에 setTimeout 의 콜백 함수가 0 초 후에 실행되는 것이 아니라 webapi 에서 해당하는 이벤트를 처리할 수 있는 시간이라고 보면 된다.
그렇기 때문에 0 초 뒤에 실행 되는 것 처럼 보이지만, 사실 최소 0 초 이상의 시간이 걸린다.

매크로 큐 스택, 마이크로 큐 스택

사실 큐 스택에도 먼저 처리가 되는 작업이 있고 나중에 처리되는 작업이 있다. 마이크로 큐 스택은 매크로 큐 스택보다 먼저 처리가 되는 작업이다.

매크로 큐 스택은 setTimeout, setInterval, setImmediate, I/O, UI rendering 등이 있다. 마이크로 큐 스택은 process.nextTick, Promise, Object.observe, MutationObserver 등이 있다.

그렇기 때문에 항상 setTimeout 의 콜백 함수가 먼저 실행되는 것이 아니라 Promise 의 콜백 함수가 먼저 실행되는 경우도 있다. 이를 유의 해서 코드를 작성해야한다.

항상 의도대로 작동을 하지 않는 다면 내가 작성한 코드가 매크로 큐 스택인지 마이크로 큐 스택인지 확인해보자.

참고

https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

profile
항상 즐겁고 재밌게!

0개의 댓글