반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

비동기는 동시가 아니다 본문

JS/인간 JS엔진

비동기는 동시가 아니다

5_hyun 2024. 1. 27. 04:12

비동기

  • 비동기는 동시에 돌아가는 것이 아니다!
  • 순서의 문제이다.

동기 코드

  • 동기 코드는 "위 -> 아래", "왼쪽 -> 오른쪽"으로 실행
  • 따라서 예측이 쉽다

비동기 코드

  • 보이는 코드대로 실행되지 않음
  • 다만 정해진 순서는 있다
  • 한 번 비동기는 영원한 비동기
    • async/await, promise 등을 써도 동기로 만들 수 없다.
    • 비동기를 동기로 바꾸려는 노력을 하지 말자

비동기 코드 분석

setTimeout(() => {
  console.log("a");
}, 0);
setTimeout(() => {
  console.log("b");
}, 1000);
setTimeout(() => {
  console.log("c");
}, 2000);

(아래 글은 정확한 JS 스펙은 아니지만 99% 맞다, 스펙을 다 공부하려면 시간이 너무 오래 걸림)

 

  1. 호출 스택(처음)
    • 우선 strict 모드가 아니면 호출 스택에 anonymous(this = window)가 들어감
    • setTimeout이 순서대로 들어감
  2. 비동기 처리
  • setTimeout은 비동기 함수라서 백그라운드, 테스크 큐, 이벤트 루프가 추가
    • 어떤 함수가 비동기인지, 비동기 중에서도 promise인지는 검색해서 아는 방법밖에 없다.
  • 백그라운드
    • 우선 백그라운드 가상의 개념이다.
    • js는 싱글 스레드라서 동시라는 개념이 없는데, 백그라운드에 들어가면 동시라는 개념이 생긴다.
      • 왜냐면 백그라운드는 엔진(C++)이거나 OS이기 때문이다.
    • 백그라운드에 들어가는거는 setTimeout의 타이머들, promise, ajax(네트워크) 요청, 이벤트 리스너 등이 들어감
      •  비동기면 적어도 백그라운드를 한 번 거치겠구나 생각하면 됨
    • 백그라운드에서 정해진 시간이 지나면 테스크 큐로 간다.
  • 태스크 큐(M)
    • 태스크 큐에는 정해진 시간이 지난 함수(fn)들이 들어간다.
    • 큐(Queue)라서 FIFO이다.
  • 이벤트 루프
    • 결국 비동기도 실행하려면 호출 스택에 올라가 있어야 한다.
    • 이벤트 루프가 호출 스택이 비어있으면 태스크 큐에서 하나씩 호출 스택으로 올려준다.
  • 호출 스택
    • 호출 스택이 비어있으면 fn(a)가 우선 호출 스택에 올라간다.
    • fn(a)와 console.log가 호출 스택에 쌓이고, 이걸 모두 실행하면 또 fn(b)와 console.log가 쌓인다.
    • 사진에서는 fn(b)까지만 그렸는데, fn(b)도 모두 실행되면 fn(c)가 쌓이게 된다.

태스크 큐에서 매크로와 마이크로

-마이크로(m)

  • promise와 process.nextTick(노드에서 사용)만 마이크로로 들어간다.
  • promise는 resolve 혹은 reject되는 순간에 마이크로(m)로 보내준다.

-매크로(M)

  • 나머지는 다 매크로로 들어간다.
  • 클릭 이벤트 리스너 같은 경우는 클릭이 되는 순간 태스크 큐의 매크로(M)로 보냄

-구분해 놓은 이유

  • 컴퓨터에 동시란 거의 없지만, 만약에 동시에 매크로(M), 마이크로(m)로 들어가면 마이크로(m)에 들어간 것부터 호출 스택에 올린다. 
  • 만약에 마이크로(m)가 무한정으로 꽉 차 있으면, 매크로(M) 부분은 실행되지 않는다. 
setTimeout(() => {
  console.log("a");
}, 0);
setTimeout(() => {
  console.log("b");
}, 1000);
setTimeout(() => {
  console.log("c");
}, 2000);
Promise.resolve().then(() => {
  console.log("p");
});
  • 이 코드의 실행 결과는 p, a, b, c 순서로 출력된다.
  • 왜냐면 Promise는 마이크로(m)에 들어가서 먼저 호출 스택에 올라가기 때문이다.

 

-출처

https://www.youtube.com/watch?v=0q_h594NDMU&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=12

 

728x90
반응형

'JS > 인간 JS엔진' 카테고리의 다른 글

async/await, Promise로 바꾸기  (1) 2024.01.28
Promise에도 동기는 있다!  (0) 2024.01.27
Promise, async/await  (2) 2024.01.25
블록 스코프와 매개변수  (0) 2024.01.24
this를 분석할 수 없는 케이스  (0) 2024.01.23
Comments