• 티스토리 홈
  • 프로필사진
    redpome
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
redpome
  • 프로필사진
    redpome
    • 분류 전체보기 (50)
      • 내일배움캠프 (23)
      • 웹개발 지식 (2)
      • 프로그래머스 (8)
      • React (7)
      • 코딩테스트 (1)
      • UI-UX (1)
      • 타입스크립트 (2)
      • Next.js (3)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • 실행 컨텍스트 (3) - 콜 스택, 마이크로 태스크
        2025년 01월 17일
        • redpome
        • 작성자
        • 2025.01.17.:12

        자바스크립트에서 실행 컨텍스트는 크게 스택과 큐로 나눌 수 있다. 싱글 스레드인 자바스크립트 엔진 특성상 병렬처리를 하기 위해 비동기적 프로그래밍을 통해 코드를 처리할 수 있다.

         

        const foo = () => {
          console.log("Execute foo");
          return Promise.resolve("foo");
        };
        
        async function bar() {
          console.log("Before await");
        
          const fooValue = await foo();
          console.log(fooValue);
        
          console.log("After await");
        }
        
        console.log("First");
        bar();
        console.log("Second");

         

        위의 코드의 결과를 직관적으로 예측하기 어려운 이유도 이와 같다.
        자바스크립트의 런타임 환경은 코드의 실행, 대기열에 존재하는 작업을 처리하는 이벤트 루프에 기반하여 처리한다. 자바스크립트 엔진에서 실행 컨텍스트 스택(콜 스택)이 비었는지 확인하고 비었을 때 태스크 큐에 있는 것을 불러와 콜 스택에 넣는다. 이렇게 되면 싱글 스레드여서 병렬처리가 불가능한 자바스크립트가 비동기 작업을 동시적으로 처리할 수 있다.

         

        Run-in-completion은 싱글 스레드인 자바스크립트의 특성처럼 작업 처리에 있어서 비선점인 특징을 가지게한다. 쉽게 말해 다른 작업이 처리되기 전까지는 다른 작업을 처리할 수 없다.

        실행 컨텍스트가 쌓이다보면 이전에 처리하던 실행 컨텍스트는 블로킹 된다. 기존에 실행하는 컨텍스트를 멈추고 콜 스택 상위에 존재하는 실행 컨텍스트를 처리한다.

         

        위의 코드를 시간 순서에 따라 처리되고 출력되는 과정은 다음과 같다.

        시간에 따른 실행 상태

         

        위의 사진에서 시간 별로 콜스택에 쌓이는 컨텍스트와 비동기 처리되는 경우의 마이크로태스크 큐에 존재하는 작업을 볼 수 있다.

        첫 번째 동기 코드인 First가 출력이 되고나서 bar()를 호출하는데 이 때 bar는 async 선언이 되어있지만 일반 함수처럼 실행 컨텍스트에 올라가고 Before await를 출력하게된다.

        이후 await선언이 된 변수 fooValue에 의해 foo()함수가 호출되고 foo()의 내부의 실행이 발생한다. 이 시점에서 Execute foo가 출력된다. 이후 console.log(fooValue)는 프로미스를 반환하며, 프로미스는 마이크로태스크 큐에 올려지게 되고 await 선언이 된 코드에 의해 bar() 컨텍스트의 실행은 동작을 멈춘다. 

        이후 전역에서 Second가 출력된다. 이 시점에서 모든 콜 스택에 실행 컨텍스트가 없어진다, 따라서 마이크로태스크 큐의 작업들이 처리가 되며 프로미스의 처리 결과인 foo가 출력된다. 마지막으로는 await에 의해 실행이 중지되었던 컨텍스트가 실행되고 After await의 출력을 마지막으로 코드 실행이 끝난다.

         

        참고로 마이크로태스크 큐와 매크로 태스크 큐가 존재하는데 이 둘의 차이는 다음과 같다.

         

        • 매크로 태스크 - 비동기 API인 콜백이 추가, setTimeout, setInterval
        • 마이크로 태스크 - 프로미스 핸들러, async 함수, process.nextTick(), queueMicrotask()

        마이크로 태스크가 매크로 태스크보다 우선 순위를 가진다.

         


        다른 예제도 함께 살펴보자.

         

        function foo() {
          try {
            setTimeout(() => {
              throw new Error("Catch me");
            }, 0);
          } catch (e) {
            console.log("catch");
          }
        }
        
        foo();

         

        이 코드는 스크립트 실행이 중단된다. foo()함수가 호출되고 새로운 실행 컨텍스트로서 콜 스택에 추가된다. 이후 try문을 거쳐 setTimeout에 의해 콜백 함수는 매크로 태스크 큐에 등록되고, 현재 실행 중인 콜 스택의 코드가 끝난 후에야 이벤트 루프에 의해 처리된다.

        이렇게 등록되고 난 뒤 foo함수는 종료된다. 콜 스택이 비워졌으므로 매크로 태스크 큐의 작업을 적재하여 실행한다.
        throw new Error("Catch me")가 발생한다. 그러나 이 에러는 try...catch 블록이 있는 컨텍스트가 아닌 다른 실행 컨텍스트에서 발생했으므로 try...catch 처리가 불가능하다. 처리되지 않은 에러는 전역 컨텍스트로 전파되며 에러를 잡을 수 없어 스크립트가 중단된다.

         

        다음은 다른 예제이다.

         

        async function bar() {
          try {
            await baz();
          } catch (e) {
            console.log("catch");
          }
        }
        
        async function baz() {
          console.log("hi");
          throw new Error("Catch me");
        }
        
        bar();

         

        bar()가 실행 컨텍스트로서 콜 스택에 적재된다. 이후 bar 함수는 비동기 함수로서 선언된 것을 알 수 있으며 try문을 실행한다. 

        await 선언된 baz()가 호출되고 baz에서 hi를 출력한다. Error인 Catch me는 프로미스로서 reject 상태가 된다. 
        reject 상태인 프로미스이므로 try...catch 블록으로 가고 catch 블록에 의해 catch가 출력된다.

        '내일배움캠프' 카테고리의 다른 글

        포켓몬 도감 만들기 -(1)  (0) 2025.02.05
        TIL - 트러블 슈팅  (0) 2025.01.23
        TIL - Scope, this 바인딩, 클래스  (2) 2025.01.15
        개인과제 - 영화 정보 사이트  (0) 2025.01.14
        TIL - 프로미스와 메서드 (1)  (1) 2025.01.10
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바