티스토리 뷰

#js #js기본

JavaScript는 단일 스레드 언어다.

한 번에 하나의 작업만 처리할 수 있다.
이러한 특성 때문에 비동기 처리 모델을 사용하여 I/O 작업 등이 진행되는 동안 다른 작업을 수행할 수 있도록 한다.

비동기 콜백 함수는 일반적으로 두 가지 종류의 큐에서 관리된다.

우선순위: micro task queue > task queue

1. 마이크로 태스크 큐 (micro task queue)

Promisethen 메서드나 async/await 등에 의해 생성된 콜백 함수가 저장되는 곳입니다.
이벤트 루프가 각 반복에서 호출 스택을 비우면, 마이크로 태스크 큐 를 확인하고 그 안의 모든 콜백을 실행합니다.

2. 태스크 큐 (task queue)

setTimeout, setInterval 과 같은 API에 의해 생성된 콜백 함수가 저장되는 곳이다.
이벤트 루프가 각 반복에서 호출 스택마이크로 태스크 큐 를 비운 후에야 확인하고 실행한다.

코드 예시 1

function aaa() {
  setTimeout(() => {
    console.log('d');
  }, 0);
  console.log('c'); 
}

setTimeout(() => {
  console.log('a');
  aaa();
}, 0);

Promise.resolve().then(() => { // ✨ then의 콜백은 resolve가 된 후 실행된다.
  aaa(); // (1)
  console.log('b'); 
});
  1. 일단, function aaa, setTimeout, Promise.resolve.then() 모두 메인 스크립트에서 동기적으로 호출
  2. setTimeout이 태스크큐에 등록 (ㄱ)
  3. Promise.resolve().then의 콜백이나 async/await의 콜백이 마이크로 태스트 큐에 등록 (ㄴ)
  4. 메인 스크립트의 동기적인 부분이 모두 완료되면, 이벤트 루프가 마이크로 태스크 큐를 확인
  5. (ㄴ) 단계 : aaa(); 실행
    1. aaa()의 setTimeout 태스크큐에 등록 (ㄷ)
    2. ‘c’ 출력
  6. ‘b’ 출력
  7. 마이크로 태스크 큐 비워지면 이벤트 루프는 태스크 큐 확인
    1. (ㄱ) 단계 : ‘a’ 출력
    2. aaa() 함수를 호출하면서 setTimeout이 등록 (ㄹ)
      1. ‘c’ 출력
      2. (ㄱ) 단계 ‘d’ 출력
  8. (ㄹ) 단계 : ‘d’ 출력

결과: c -> b -> a -> c -> d -> d

[!note] Promise.resolve.then에서 aaa(); console.log(‘b’) 는 동기적으로 일어난다.
c가 출력되고, setTimeout의 콜백이 태스크 큐에 등록 된 후, b가 출력이 된다.

코드 예시 2

console.log('1');

setTimeout(function() {
  console.log('2');
}, 0);

Promise.resolve()
  .then(function() {
    console.log('3');
  })
  .then(function() {
    console.log('4');
  });
  
console.log('5');
  1. 1 출력, 5출력
  2. setTimeout의 콜백을 태스크 큐에 등록 // 0초의 지연 시간 후에 태스크 큐에 추가.
  3. Promise.then의 콜백을 마이크로 태스크 큐에 등록
    1. 메인 스크립트의 동기 작업이 완료가 되면, 이벤트 루프는 마이크로 태스크 큐를 확인하고 그 안의 모든 작업을 처리한다.
      1. 3 출력
      2. 4 출력
  4. 태스크 큐 확인 후 2출력

출력결과: 1 -> 5 -> 3 -> 4 -> 2

코드 예시 3

console.log('1');

setTimeout(function() {
  console.log('2');
  
  Promise.resolve().then(function() {
    console.log('3');
  });
}, 0);

Promise.resolve()
  .then(function() {
    console.log('4');
  })
  .then(function() {
    console.log('5');
  });

console.log('6');
  1. 1 출력, 6출력
  2. setTimeout 콜백이 태스크 큐에 등록 (2)
  3. 프로미스의 then 체인 콜백이 마이크로 태스크 큐에 등록 (4, 5)
  4. 이벤트 루프가 마이크로 태스크 큐를 확인
    1. 4, 5 출력
  5. 마지막으로 태스크 큐 확인하여 2 출력
    1. 그 후 새롭게 생성된 Promise가 마이크로 태스크 큐에 등록
    2. 3 출력

[!note] setTimeout 내부에 생성된 Promise 역시 해당 시점에서 가장 우선순위가 낮은 비동기 작업으로 처리된다.

출력 결과: 1 -> 6 -> 4 -> 5 -> 2 -> 3

Pasted image 20231218104521.png

코드 예시 4

function test() {
  return new Promise((resolve, reject) => {
    resolve();
      console.log('step1');
    })
}

test()
  .then(() => {
    console.log('step2')
  })
  .catch(() => {
    console.log('error')
  })
  1. test() 가 호출되고 프로미스 객체가 생성
  2. resolve() 실행 -> ‘step1’ 출력 // Promise 내부 함수는 마치 동기적으로 흐른다.
  3. then() 실행 -> ‘step2’

결론: 비동기 작업은 규칙에 따라 처리 순서가 결정된다.

코드를 보고 알 수 있는 점?

JavaScript에서 비동기 작업은 정해진 규칙에 따라서 처리 순서가 결정이 되고,
이 규칙은 Promise(마이크로 태스크)와 setTimeout(태스트) 사이에서도 차별화 된다.

(혹시 틀린 정보가 있다면 댓글로 알려주세요!)

  • 이 글은 옵시디언에서 작성되었습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함