ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] JavaScript Event Loop
    JavaScript 개념 2022. 7. 3. 14:26

    Event Loop란?

    Event Loop는  callbackqueue를 주기적으로 주시하고있다가 stack이 비워지면 callback queue에서 기다리고 있던 값을 stack넘겨주는 역할

     

    이렇게 말을 하니까 무슨말인지 잘 모르겠다 (ㅜ-ㅜ ) 이걸 이해하기 위해서는  JavaScript가 어떻게 동작하는지 알아야한다 아래 예시를 봐보자!!

    JavaScript Engine

    위 그림이 JavaScript가 돌아가는 방식이다.

    이제 저 하나하나가 무슨역할을 하는지 알아보자

     

     

    Stack

    JavaScript에서 함수가 실행될때마다 쌓이는 곳(접시가 쌓이는것처럼 쌓인다고 생각하면 된다.)

    function foo(b){
        var a= 10;
        return a + b;
    }
    
    function bar(x){
        var y = 2;
        return foo(x+y);
    }
    
    console.log(bar(1));
    // 출력값 ->13

    위 코드를 살펴보자.

    우리는 먼저 bar 함수를 호출했다. 그리고 `bar`함수는 `foo`함수를 호출하고 있다. 아직 `bar`함수는 종료가 되지 않았으니 출력이 되지 않는다. 그리고 bar함수위에 foo함수가 호출이 된다.`foo`함수에서는 `a+b`라는 값을 return 하면서 함수의 역할을 모두 마쳤으므로 stack에서 pop된다. 다시 `bar`함수로 돌아와서 `foo`함수로부터 받은 값을 return하면서 `bar`함수도 종료되고 stack에서 pop된다

     

    Web API

    JavaScript에서 비동기 함수들을 처리해주는 곳이다!

    Heap

    동적으로 생성된 객체(인스턴스)는 힙(heap)에 할당된다. 대부분 구조화 되지 않는 '더미'같은 메모리 영역을 `heap`이라 표현한다.

     

    Callback Queue(Task Queue)

    자바스크립트의 런타임 환경에서는 처리해야 하는 Task들을 임시 저장하는 대기큐가 존재한다.

    그 대기 큐를 Event Queue라고 한다. 그리고 Call Stack이 비어졋을 때 먼저 대기열에 들어온 순서대로

    수행된다.

    const foo = () => console.log("First");
    const bar = () => setTimeout(() => console.log("Second"), 500);
    const baz = () => console.log("Third");
    
    bar();
    foo();
    baz();

    자바스크립트는 비동기 함수가 들어오면 그것을 callStack에서 실행하지 않고WebAPI로 넘긴다. 거기서 비동기 함수들이 실행이 되고 실행을 끝낸 순서대로 QUEUE에 쌓인다. EventLoop는 항상 Stack과 queue를 주시하면서  stack 다 비었으면 queue에서 실행아 다된 함수들을  stack으로 넘긴다.  아래 예시가 자바스크립트가 작동되는 원리이다!

     

    이제 이 설명을 다 듣고 나면 Event Loop가 어떤것인지 알수있을것이다.

     

    function test1(){
        console.log('test1');
        test2();
    }
    
    function test2(){
        let timer = setTimeout(function(){
            console.log('test2');
        },0);
        test3();
    }
    
    function test3(){
        console.log('test3');
    }
    
    test1();
    
    // 출력값 
    // test1
    // test3
    // test2

    이제 test1()을 호출했을 때 어떠한 순서로 출력되는지 예측할수 있어야 한다.

    일단 "test1"이 출력되고, 그리고 test2()가 호출되면서 `setTimeOut`함수가 실행되고 콜스택에 들어간다음,

    바로 빠져나온다. 그리고 내부에 걸려있던 핸들러(익명함수)는 콜스택에 들어가서 바로 실행되지 않는다. 

    이 부분이 중요하다. 이 핸들러는 call stack 영역이 아닌 event queue 영역으로 들어간다. 그리고 test3 함수가 콜스택으로 들어간다.

    test3()이 실행되면서 'test3'이 console에 찍히고, 작업을 모두 마친 test3 함수가 Call stack에서 pop된다.

    이어서 test2 함수와 test1 함수까지 Call stack에서 pop된다. 이때 Event Loop 콜스택이 비어있게 된다.

    이 시점에서 queue의 head에서 하나의 event를 가져와서 Call Stack으로 넣는다.이 이벤트는 setTime 함수 내부에 있던

    익명함수이다. 이제서야 이 함수가 실행된다.

     

    즉, test3이 끝나고(Call Stack에서 Pop되고) test2가 끝나고, test1이 마저 끝나고 이벤트 루프에 의해 하나의 event가 

    dequeue가 된 다음 콜스택으로 들어가서 실행된다. 그러므로 이벤트에 걸려있는 핸들러는 절대 먼저 실행될 수 없다!

     

    queue에 메시지, 즉 처리해야할 이벤트(또는 태스크)가 존재하면 while-loop안으로 들어가서 해당하는 이벤트를 처리하거나 작업을 수행한다. 그리고는 다시 queue로 돌아와 새로운 이벤트가 존재하는지 파악하는 것이다. 

    Event Queue에서 대기하고 있는 Event들은 한번에 하나씩 Call Stack으로 호출되어 처리된다.

     

    이벤트 루프에 대한 대랴적인 설명이다 자세한 설명을 읽어보고 싶다면 아래에서 확인할 수있 잇다.

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

    https://www.nextree.co.kr/p7292/

     

    The event loop - JavaScript | MDN

    JavaScript has a runtime model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks. This model is quite different from models in other languages like C and Java.

    developer.mozilla.org

    출저:https://asfirstalways.tistory.com/362

Designed by Tistory.