JavaScript 비동기(예시로 Event Loop를 이해해보자)

아직 자바스크립트에서 비동기 함수가 어떻게 진행되는지 이해하지 못했다면 [javascript는 어떻게 돌아갈까? 1편] 부터 학습하시면 됩니다.

예시로 배우는 Event Loop(이벤트 루프)

1.동기함수와 비동기함수

//다음 코드의 출력 결과는?????
function one(){
  console.log('one');
}

function two(){
  console.log('two');
}

setTimeout(two,0);
one();

/*
* 정답
* one
* two
*/

어떻게 'one'이 먼저 출력됐을까 ??

2.비동기함수와 비동기함수

//다음 코드의 출력 결과는?????
function one(){
  console.log('one');
}

function two(){
  console.log('two');
}

function oneSetTimeout(){
  console.log('set one');
  setTimeout(one,0);
}

function twoSetTimeout(){
  console.log('set two');
  setTimeout(two,0);
}

setTimeout(oneSetTimeout,0);
setTimeout(twoSetTimeout,0);

/*
* 정답
* set one
* set two
* one
* two
*/

어떻게 이렇게 출력이 됐을까 ??

3.MicroTask와 Task

function one(){
  console.log('one');
}

function three(){
  console.log('three');
}

setTimeout(one,0);

new Promise((resolve)=>{
	resolve('two');
}).then((res)=> console.log(res));

three();

/*
* 정답
* three
* two
* one
*/

어떻게 이렇게 출력이 됐을까 ??

setTimeout(func, 0)은 도대체 왜 사용하는거지 ?

위 예제 뿐만아니라 여러 코드에서 관용적으로 setTimeout(fn, 0)을 사용하는 것을 보셨을 겁니다.

하지만 실제로 setTimeout(fn,0) 의 비동기적 실행 방식이 요긴하게 쓰인다는 것 알고 계신가요 ??
아래의 Ajax를 사용한 코드를 한번 봐보겠습니다.

$('.btn').click(function() {
    showWaitingMessage();
    longTakingProcess();
    hideWaitingMessage();
    showResult();
});

위 예제에서 함수들을 간단히 설명하겠습니다.

  • showWaitingMessage : '로딩중' 메세지를 보여주기 위한 함수입니다.
  • longTakingProcess : 긴 작업 시간이 필요한 함수입니다.
  • hideWaitingMessage : '로딩중' 메세지를 지우기 위한 함수입니다.
  • showResult : longTakingProcess 이 끝난 후 결과를 보여주는 함수입니다.

사용자는 긴 작업 시간이 필요한 longTakingProcess 함수를 기다리는 동안 showWaitingMessage 함수를 통해 '로딩중' 메시지를 보여주고 싶습니다.

하지만 '로딩중' 을 표시하기 위한 이벤트 핸들러는 비동기 적으로 일어나기 때문에 Call Stack안에 있는 longTakingProcess, hideWaitingMessage, showResult 함수가 비어져야 실행될 수 있습니다.

이를 문제를 해결하기 위한 방법으로 setTimeout(fn,0) 을 사용할 수 있습니다.

$('.btn').click(function() {
    showWaitingMessage();
    setTimeout(function() {
        longTakingProcess();
        hideWaitingMessage();
        showResult();
    }, 0);
});

이렇게 실행하게되면, showWaitingMessage가 실행되고, Web API에게 DOM Event를 요청하여 콜백함수를 먼저 Event queue로 보내 '로딩중' 메세지를 보여줄 수 있습니다.

마치며

앞으로도 추가적으로 도움이 될만한 예시가 있다면, 가져와서 내용을 추가해보겠습니다 !

Event Loop가 실행되는 방법이 생각보다 까다롭기 때문에 차분히 생각하는 시간과 증명하는 시간이 필요했습니다.

HTML5 Spec [중첩된 타임아웃이 4ms 이하일 경우]을 보면 타임아웃(중첩 5이상)의 최소 지연시간이 4ms라고 나와있습니다. 이것이 중첩 5이상이 아닐 때는 어떻게 적용되는지 한번 더 확인이 필요할 것 같습니다.

이부분도 추후에 정리해서 올려보겠습니다. 😋

참고 : https://meetup.toast.com/posts/89

좋은 웹페이지 즐겨찾기