동기 & 비동기 - Stack,Queue

최문길·2023년 11월 7일
2

JavascriptES6

목록 보기
19/23

동기 VS 비동기

자바스크립트는 동기적으로 처리됩니다.

물론 비동기적인 처리도 가능하게 된다.

  • setTimeout
  • EventListenr
  • ajax
  • etc...
    특정 코드를 사용하면 비동기적으로 처리가 ' 된 '다.

동기적

1 + 1 

setTimeout(1초후 2+2)

3 + 3

실생순서는 2 => 1초 후 4 => 6
( 동기적 처리는 하나씩 하나씩 순차대로 처리하는 것 )

비동기적

1+1

setTimeout(1초 후 2+2)

3+3

실행순서는 2 -> 6 -> 1초 후 4
( 비동기는 하나 처리하고 시간 걸리는 건 따로 빼두고 그 다음 것을 처리 후 시간걸리는 것을 처리하는 것 )

열차 ( 동기 ) VS 택시 ( 비동기 ) -전 이런식으로 최대한 컴퓨터와 유사한 것을 생각해서 이해 하였습니다.


웹브라우저의 동작 원리

Q . 왜 알아야함?

A .

  • 자바스크립트는 그냥 구동 되지 않으셈. 마법적인 성질이 없다.
    우리의 크롬짱이 실행 해 주니까
  • 우리의 웹 브라우저(오페라, 크롬,IE, firefox..등)가 자바스크립트를 실행 해주는 엔진임!

브라우저는 C++이라는 어마무시한 언어로 코드가 짜여져있다.
브라우저는 실행할 자바스크립트 코드를 발견하면 Stack에 넣고 running 한다. - stack은 그냥 코드 다 집어 넣고 맨 윗줄 부터 하나하나 실행시키는 공간이라 생각하자...

그런데!!!

처리가 오래 걸리는 특별한 코드를 만나면..
( 예를 들면 서버로의 ajax요청, 이벤트리스너, setTimeout등.. )
이런 코드 처리까지 '상대적'으로 시간이 오래걸린다.
  1. ajax요청은 서버에서 응답 받기 까지 오래 걸리고
  2. 버튼 이벤트리스너는 버튼 누르기전까지 시간이 걸리고

그래서 그런건 브라우저가 Stack 공간에 쌓아두지 않고
잠깐 보류후(Web API등...)에서 대기 했다가 Queue로 차례 차례
집어 넣고 Stack이 텅 빈 시점에 차례차례 집어넣어 실행한다.

브라우저의 stack과 Queue

stack

  • 내 코드( HTML,CSS,JAVASCRIPT ) 실해주는 곳 : 특징은 하나 밖에 없음 그래서 자바스크립트는 single threaded language이다.
  • 한번에 하나씩 밖에 처리 못함 ㅜㅜ

Queue ( = 대기실 )

  • 특징: stack이 비어있을 때 '만' 코드를 " 순서대로 " " 하나 씩" stack에 보내버림

  • 특정 코드를 옮겨 보관하는 곳
    - 자바스크립트가 브라우저에 의해 실행되면 반드시 대기실에 옮겨 놓는 코드가 몇 개 있음 ( 실행 오래걸리는 code들 )

    1. Ajax요청
    2. EventListenr
    3. setTimeout(이친구는 Web Api 갔다가 Queue로 옴) 등...


Sample - Stack & Queue

stack queue
코드 1번 <- 첫 번째 실행 Queue대기순서 : 1 Ajax요청 <- 4번째 실행
코드2번 <- 2번째 실행 Queue대기순서 : 2 이벤트리스너 <- 5번째 실행
코드3번 <- 3번째 실행 Queue대기순서 : 3 setTimeout <- 6번째 실행

실행 순서는 " 코드1 → 코드2 → 코드3 , 그리고 Queue에 있는 4 , 5 , 6번째가 실행 예정이 었지만 " ...

그런데 stack에 코드4번이 '코드 3번까지 실행 후' 추가 되면?

stack queue
코드 4번 <- 먼저 (첫 번째) 실행 Queue대기순서 : 1 Ajax요청 <- 4번째 실행
Queue대기순서 : 2 이벤트리스너 <- 5번째 실행
Queue대기순서 : 3 setTimeout <- 6번째 실행

코드 4번이 먼저 실행된다.
그러고 난 후 코드 5번, 코드6번이 차례로 Queue에서 Statck으로 가지만, 그런데 !!!😣 여기서 또 이벤트 리스너2가 호출되면...

브라우저에선...

stack queue
코드 5번 <- 먼저 (첫 번째) 실행 Queue대기순서 : 1 Ajax요청 <- 3번째 실행
코드6번 <- 두 번째 실행 Queue대기순서 : 2 이벤트리스너 <- 4번째 실행
Queue대기순서 : 3 setTimeout <- 5번째 실행
new Queue대기순서 : 4 이벤트리스너 2 <- 6번째 실행

이렇게 " 코드 5번 → 코드 6번 → Ajax요청 → 이벤트리스터 → 이벤트리스너2 실행 순서가 된다.




따라서

// 이 코드를 브라우저가 해석하면
console.log ( 1 + 1 )
setTimeout(function(){console.log(2+2)}, 3000); 
console.log ( 2 + 2 ) 
setTimeout(function(){console.log(8+2)}, 1000); 
stack queue
console.log ( 1 + 1 ) <- 먼저 (첫 번째) 실행 setTimeout (Web API에서 1초지나면 Queue로 보내짐); <- 3번째 실행
console.log ( 2 + 2 ) <- 두 번째 실행 setTimeout(Web API에서 3 초지나면 Queue로 보내짐); <- 4번째 실행

실행 순서는
1. console.log( 1 + 1 )
2. console.log( 2 + 2 )
3. setTimeout(function(){console.log(8+2)}, 1000); // Web API에서 1초가 지나면 Queue로 '먼저' 보내짐
4. setTimeout(function(){console.log(2+2)}, 3000); // 그다음 Web API에서 3초가 지나면 Queue로 '그 다음' 보내져 stack으로 들어가게 된다.

Q. setTimeout의 시간을 0초로 주게 되면?

console.log( 1 + 1 ) // 첫 번째로 실행
setTimeout( () => console.log( 2 + 2 ) , 0 ) // 2번 째로 실행
console.log( 2 + 2 ) // 3 번째로 실행

위 코드 처럼 될까?

A. 그런거 없다... 너무나 가혹함...

stack queue
console.log ( 1 + 1 ) <- 먼저 (첫 번째) 실행 setTimeout (Web API에서 0초지나면 Queue로 보내짐); <- 3번째 실행
console.log ( 2 + 2 ) <- 두 번째 실행

실행 순서는
1. console.log ( 1 + 1 )
2. console.log ( 2 + 2 )
3. setTimeout ( 0 초 )
순으로 실행된다.


교훈

  1. stack을 바쁘게 하지 말자
  2. Queue를 바쁘게 하지 말자
    -> 버튼누르면(이벤트리스너) 모달창 *10000개 띄워주셈 하면 Queue에서 Stack에 올려보내는 것도 힘들고(= stack이 한가하게 맨날 비어있지 않을거임), 다른 Queue에 들어간 코드들도 실행지연이 생겨버림

Q. 그러면 코드 어떻게 짜라는걸까..

A. SetTimeout, Web worker.js

SetTimeout을 이용하자

code 1
code 2
code 3
code 4
.
.
.
setTimeout( () => {
  for (let i = 0; i < 1e10 ; i++) {
    i++
  }
} , 0 )

// 참고로 setTimeout 타이머를 0초로 설정해도 실은 4ms로 동작한다고 함
//설정가능한 최소시간이 4ms 임

이렇게 공손하게 setTimeout을 이용하면 브라우저가 자바스크립트를 싹 다 훑고 마지막에 for문 식 ( = 복잡하고, 무서운 계산식 같은것 )을 계산해서 해결 가능

Web worker를 이용

이미 만들어져 있는 Worker라는 클래스가 있다.

다른 자바스크립트 파일을 이용해서
그 파일에서 힘든 연산을 시키고 그게 완료가 되면 값을 가져오라고 명령이 가능하다.
( 이미 만들어진 Worker라는 클래스를 사용하면 됩니다. )

( 메인 js 파일 )

var myWorker = new Worker('worker.js');
w.onmessage = function(e){
  console.log(e.data) //이러면 calculated계산식이 나옴
};

---------------------
  
(worker.js 파일)
var calculated = for (let i = 0; i < 1e10 ; i++) {
    i++
  } ;
  
postMessage( calculated ); //postMessage라는 특별한 함수가 있음

회고

점점 코드를 만들고 수정하면서 이러 한 효율적인 코드짜기 같은 것도 눈에 밟혀 참 좋기도 하다

0개의 댓글