ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • fetch를 학습하다 JavaScript 동작원리를 학습한 건에 대하여...
    Language/JavaScript 2023. 11. 19. 18:33

    fetch 

    fetch는 JavaScript에서 서버로 네트워크 요청을 보내고 응답을 받을 수 있도록 해줍니다.

    첫 번째 인자로 URL, 두 번째 인자로 옵션 객체를 만들고, Promise 타입의 객체를 반환해 줍니다.

    비동기 방식으로 요청하기 때문에 자동으로 다음 코드로 넘어갑니다.

    하지만, API로부터 받아온 정보를 사용할 필요가 있는 경우가 있는데 이럴 때 사용하는 것이 then입니다.

    then

    앞서 언급했듯이 fetch는 비동기 함수입니다.

    then은 그런 fetch의 응답을 then에 전달된 콜백으로 처리할 수 있도록 해주는 fetch의 메서드입니다.

    fetch의 다른 메서드인 catch와 finally도 비슷하게 동작합니다.

    그렇다면 fetch의 메서드들은 어떻게 비동기로 동작하는 fetch의 응답을 기다렸다가 전달된 콜백을 처리할 수 있을까요?

    JavaScript Runtime

    Runtime

    아시다시피 JavaScript는 싱글 스레드 언어입니다. 

    쉽게 말하면 한 번에 한 가지 일 밖에 처리할 수 없다는 뜻입니다. (어렵게 말하면 Call Stack이 하나라는 뜻)

    어려운 말 쓰면 있어 보이니깐 먼저, 콜 스택이 뭔지 알아봅시다.

    콜 스택 (Call Stack)

    콜 스택은 함수 호출을 추적하는 자료 구조입니다.

    JavaScript는 함수 호출을 콜 스택에 추가하고 완료되면 콜 스택에서 제거합니다.

    즉, 함수가 실행이 끝나면 다음에 실행할 일을 정할 때 사용하는 것이 콜 스택이라고 할 수 있습니다.

    그럼 여기서 비동기 함수인 fetch는 어떻게 동작하는지 의문이 들 수 있습니다. 

    여기서 우리는 웹 API에 대해서 알아야 할 필요가 있습니다.

    웹 API (Web API)

    웹 API는 브라우저 환경에서 제공되는 비동기 작업을 처리하기 위한 인터페이스 집합입니다.

    웹 API가 비동기 작업을 처리할 수 있는 이유는 브라우저 안에 C++로 구현된 스레드로 해당 작업들을 처리하기 때문입니다.

    그리고 이 스레드는 동작을 완료하는 순간 전달받았던 콜백 함수를 JavaScript의 콜백 큐에 전달합니다.

    콜백 큐 (Callback Queue)

    콜백 큐는 태스크 큐(Task Queue), 이벤트 큐(Event Queue)라고도 불리며 웹 API를 처리하는 스레드로부터 전달받은 콜백 함수들을 저장하고 있는 자료구조입니다.

    여기에 저장된 콜백함수들은 콜 스택에 순서대로 푸시되는데 한 가지 조건이 있습니다.

    바로 콜 스택이 비어있는 순간에 콜백 큐에서 순서대로 콜 스택에 푸시된다는 것입니다.

    그럼 콜 스택이 비어있는지 콜백 큐는 어떻게 알 수 있을까요?

    이벤트 루프 (Event Loop)

    바로 이벤트 루프가 존재하기 때문에 알 수 있습니다.

    이벤트 루프는 매 순간 콜 스택이 비어있는지 아닌지와 콜백 큐에 기다리고 있는 콜백 함수가 있는지를 확인합니다.

    따라서, 이 이벤트 루프가 JavaScript에서 비동기를 관리하는데 핵심적인 역할을 한다고 할 수 있습니다.

    그래서 fetch와 then이 어떻게 동작하는 건데?

    일단 이해하기 쉽게 예제 코드를 가져와서 설명하겠습니다.

    const apiUrl = 'https://abcd.com';
    
    fetch(apiUrl) // 웹 API가 처리
      // 응답이 fullfilled 상태이면, then의 콜백을 콜백 큐로 넘김
      .then((response) => response.json()) 
      .then((data) => {
        console.log('API에서 가져온 데이터:', data);
      })
      // 응답이 rejected 상태이면, catch의 콜백을 콜백 큐로 넘김
      .catch((error) => {
        console.error('Fetch 오류:', error);
      });

    1. fetch 함수가 호출되면, 비동기 작업이 시작됩니다. 

       fetch는 브라우저의 웹 API에 의해 처리되며, 네트워크를 통해 데이터를 요청합니다.

    2. fetch는 Promise를 반환하면 Promise의 상태에 따라 then 혹은 catch에게 전달된 콜백 함수가 콜백 큐에 추가됩니다.

    3. 이벤트 루프는 콜백 큐에 대기 중인 콜백 함수를 확인하고, 콜 스택이 비어있는지 확인합니다.

       콜 스택이 비어있으면, 이벤트 루프가 콜백 큐에 대기 중 인 콜백 함수를 콜 스택에 추가합니다.

    4. 콜백 함수가 콜 스택에 추가되면 실행이 됩니다.

    코드 상에서 then이 연속으로 두 번 나왔는데, then의 반환 값 역시 Promise 객체이기 때문에, 첫 번째 then과 같은 방식으로 동작합니다.

    여담

    콜백 큐에 대해 알아보는 과정에서 마이크로 태스크 큐(Micro Task Queue)라는 것도 알게 되었습니다.

    마이크로 태스크 큐 (Micro Task Queue)

    마이크로 태스크 큐는 콜백 큐보다 우선순위가 높습니다.

    마이크로 태스크 큐는 Promise와 관련된 콜백 함수들이 대기하는 자료 구조입니다.

    보통의 콜백 큐에는 setTimeout, setInterval와 같은 JavaScript에서 timing을 제어하는 함수 등에서 넘겨주는 콜백이 들어갑니다.

    결과적으로 fetch와 then을 사용할 때는 Promise를 사용하기 때문에 일반적인 콜백 함수들보다 높은 우선순위를 가지게 되어, 비동기 코드의 실행 순서를 고려해야 할 때는 이를 염두에 둬야 합니다.

    후기

    처음엔 fetch를 어떻게 잘 쓸 수 있을까에서 학습을 시작하였는데, 끝나고 보니 JavaScript 동작원리를 학습하고 있었습니다.

    하지만, 어떻게 생각하면 가장 중요한 부분을 학습한 것이고 fetch의 동작 원리를 알려면 꼭 알아야 하는 부분이기 때문에 의미 있는 시간이었다고 생각합니다.

    아니 정말 중요한 시간이었다고 생각합니다.

    앞으로 한번 공부할 때 제대로 공부하고, 틈틈이 복습하면서 복기하는 시간을 가져보도록 해야겠습니다.

     

    참고

    https://medium.com/sessionstack-blog/how-does-javascript-actually-work-part-1-b0bacc073cf

    https://ko.javascript.info/microtask-queue

    'Language > JavaScript' 카테고리의 다른 글

    JavaScript에서의 this  (0) 2024.03.06
Designed by Tistory.