본문 바로가기
Programming Language/Javascript

[Javacript] 동기와 비동기, 이벤트 루프와 태스크 큐

by ggyongi 2024. 6. 15.
반응형

동기와 비동기

동기(Synchronous)

작업이 순차적으로 실행

이전 작업이 완료되기 전까지는 다음 작업을 시작하지 않음

코드의 실행 흐름과 결과가 예측 가능

단점: 하나의 작업이 오래 걸리면 전체 프로그램이 멈춤

 

동기 코드 예시 - 3초 딜레이 주기

console.log("Start");

function delay() {
  const start = Date.now();
  while (Date.now() - start < 3000) {} // 3초 동안 블로킹
  console.log("Delay done");
}

delay();
console.log("End");

출력

Start
Delay done
End

 

비동기(Asynchronous)

작업이 즉시 실행되지 않고, 백그라운드에서 처리됩니다.

다른 작업과 동시에 진행될 수 있으며, 작업이 완료되면 콜백 함수가 실행됩니다.

이벤트 루프를 통해 처리됩니다.

 

비동기 코드 예시 - setTimeout 함수

console.log("Start");

setTimeout(() => {
  console.log("Timeout done");
}, 3000);

console.log("End");

결과

Start
End
Timeout done

 

싱글스레드

JavaScript는 싱글스레드(Single-threaded) 언어로, 모든 코드를 순차적으로 실행하며 한 번에 하나의 작업만 실행함.

근데 setTimeout과 같은 비동기 함수의 동작은 마치 여러 개의 동작을 동시에 수행하는 것처럼 보이게 함.

이런 비동기작업은 어떻게 처리하는 걸까? -> 이벤트 루프를 사용

 

이벤트 루프

 싱글 스레드 방식의 자바스크립트가 마치 여러 태스크를 동시에 처리하는 것처럼 보이는 이유는 이벤트 루프가 동시성을 지원하기 때문이다. 이벤트 루프는 브라우저에 내장되어있는 기능 중 하나다.

1. 콜 스택

실행 컨텍스트가 추가되고 제거되는 스택 자료구조이다. 함수가 호출되면 함수 실행 컨텍스트가 순차적으로 콜 스택에 푸시되어 순차적으로 실행된다. 

 

2. 힙

힙은 객체가 저장되는 메모리 공간이다. 콜 스택 요소인 실행 컨텍스트는 힙에 저장된 객체를 참조한다. 

 

콜 스택과 힙을 이용하여 자바스크립트 엔진은 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 실행할 뿐이다. 비동기 처리에서 소스코드의 평가와 실행을 제외한 모든 처리는 자바스크립트 엔진을 구동하는 환경인 브라우저 또는 Node.js가 담당한다.

 

3. 태스크 큐

비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역이다.

 

4. 이벤트 루프

이벤트 루프는 콜스택에 현재 실행중인 실행컨텍스트가 있는지, 태스크 큐에 대기중인 함수가 있는지 반복해서 확인한다. 만약 콜스택이 비어있고 태스큐 큐에 대기중인 함수가 있으면 이벤트 루프는 순차적으로 태스크 큐에 대기중인 함수를 콜스택으로 이동시킨다.

 

5. Web APIs

Web APIs는 브라우저가 제공하는 기능으로, JavaScript가 싱글스레드의 한계를 극복하도록 돕는 역할로 타이머, HTTP 요청, DOM 이벤트 등을 처리한다. 작업 완료 후 콜백 함수를 태스크 큐에 추가.

 

예시) fetch 함수를 통한 HTTP 요청

console.log("Start");

fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then((response) => {
    console.log("Response received");
    return response.json(); // JSON 변환 (JavaScript 엔진 처리)
  })
  .then((data) => {
    console.log("Data processed:", data.title);
  });

console.log("End");

출력 결과

Start
End
Response received
Data processed: title

 

작업 흐름

console.log("Start"): Call Stack에서 실행.
fetch: Web API에 네트워크 요청 위임.
console.log("End"): Call Stack에서 실행.
네트워크 요청 완료 → Web API가 첫 번째 then 콜백을 태스크큐에 추가.
이벤트 루프가 Task Queue에서 첫 번째 then 콜백을 가져와 실행.
첫 번째 then에서 JSON 변환(response.json()) 실행.
JSON 변환이 완료되면 두 번째 then 콜백을 태스크큐에 추가.
두 번째 then 콜백 실행 → 데이터 출력.

 

주의할 점

싱글 스레드 방식으로 동작하는 것은 브라우저가 아니라 브라우저에 내장된 자바스크립트 엔진(힙, 콜스택 들어있는 곳만)이다. 만약 모든 자바스크립트 코드가 자바스크립트 엔진에서 싱글 스레드 방식으로 동작한다면 자바스크립트는 비동기로 동작할 수 없다. 즉 자바스크립트 엔진은 싱글 스레드로 동작하지만 브라우저는 멀티 스레드로 동작한다. setTimeout 함수의 모든 처리가 자바스크립트 엔진에서 싱글 스레드로 수행된다면 타이머 기다리는 대기 시간동안 어떠한 태스크도 실행할 수 없을 것이다.  

(타이머를 3초롤 맞췄다면 브라우저는 어쨌든 다른 작업을 하다가도 3초 뒤에 태스크큐로 콜백함수를 추가시켜야 함)

 

 

 

 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글