JavaScript - 동기, 비동기, 이벤트루프, Web APIs

DW J·2022년 9월 13일
0

develop_wis

목록 보기
8/9
post-thumbnail

TODO Project 진행 중 init시점에 저장되어 있는 데이터를 화면에 그려주기 위해 API호출을 하였고, 그 과정에서 데이터를 가져오는 로직이 비동기(async/await) 로 처리되다 보니 런타임에서는 데이터를 가져오지 못하는 현상이 발생하였습니다. 하나의 파일(같은 함수) 에서 작업할 때는 이러한 문제가 발생하지 않았는데 파일분리(다른 함수) 후 이와 같은 문제가 발생하여 관련 내용을 찾아보게 되었습니다. 이를 해결하는 과정 에서 이벤트 루프에 대해 알게 되었고 이벤트 루프가 무엇이며 어떻게 동작하는지 궁금하여 블로그를 작성하게 되었습니다


싱글 스레드

  • 자바스크립트는 싱글 스레드 프로그래밍 언어이다
  • 싱글 스레드는 하나의 프로그램에서 동시에 하나의 코드만 실핼할 수 있다
  • 싱글 스레드는 코드가 실행되서 끝난 지점과 다음 코드의 시작 지점이 연결 된 형태이다
  • 각 스레드는 한 번에 하나의 작업만 수행할 수 있다
  • 각 작업은 순차적으로 실행된다 (다음 작업을 시작하기 전에 이전 작업을 완료해야 한다)
  • 싱글 스레드는 하나의 힙 영역과 하나의 콜 스택만을 가진다
  • 싱글 스레드는 동기적(순차적)으로 일을 처리한다

힙과 콜스택

  • 자바스크립트 엔진(V8)에는 두가지 구성 요소(힙, 스택)가 있다
  • 힙은 변수와 객체가 메모리 할당에 사용되는 비정형 메모리이다
  • 콜 스택은 하나만 존재한다
  • 콜 스택은 코드를 읽고 함수가 실행되는 순서를 기억하고 있다
  • 함수가 실행되면 스택의 가장 위에 해당 함수를 넣고, 함수의 실행이 종료되면 스택의 가장 위쪽으로 함수를 꺼낸다

동기

동기 방식은 서버에서 요청을 보냈을 때 응답이 돌아와야 다음 동작을 수행할 수 있다
A작업이 모두 진핼 될 때까지 B작업은 대기해야한다.

function task1() {
	console.log("a"); // 1
}

function task2() {
  for (let i = 0; i < 1000; i++) {
      console.log("b"); // 2 x 1000
  }
}

function task3() {
	console.log("c"); // 3
}

task1();
task2();
task3();

실행결과) a > b x 1000 > c

비동기

비동기 방식은 반대로 요청을 보냈을 때 응답 상태와 상관없이 다음 동작을 수행할 수 있다.
A작업이 시작되면 동시에 B작업이 시작된다. A작업은 결과값이 나오는 대로 출력 된다
웹 브라우저의 Web APIs는 비동기로 처리된다

function task1() {
	console.log("a"); // 1
}

function task2() {
  setTimeout(() => {
  	for (let i = 0; i < 1000; i++) {
        console.log("b"); // 3 x 1000
    }
  }, 100);
}

function task3() {
	console.log("c"); // 2
}

task1();
task2();
task3();

실행결과) a > c > b x 1000

이벤트 루프

  • 자바스크립트 런타임에서 제공하는 비동기 콜백을 만드는 것 > 이벤트 루프
  • 이벤트 루프의 역할은 콜 스택과 콜백 큐를 주시하는 것이다
  • 콜 스택이 비어 있으면 큐의 첫 번째 콜백을 스택에 쌓아 효과적으로 실행할 수 있게 한다
  • 이벤트 루프는 콜 스택이 비어질 때까지 기다린 후 콜백 큐에 있는 콜백을 콜 스택에 넣어주는 역할을 한다
  • Web API의 콜백이 완료되었다면 콜백은 큐에 쌓이게 되고, 이벤트 루프에 의해서 실행된다
  • 모든 종류의 Web API는 동일한 방식으로 동작한다
  • 이 과정은 비동기 함수가 호출되는 방식이다

이벤트 루프는 현재 실행중인 태스크가 없는지, 태스크 큐에 태스크가 있는지를 반복적으로 확인하는 역할을 한다.

  • 모든 비동기 API들은 작업이 완료되면 콜백 함수를 태스크 큐에 추가한다
  • 이벤트 루프는 현재 실행중인 태스크가 없을 때 태슼느 큐의 첫 번째 태스크를 꺼내와 실행한다
function delay() {
    for (var i = 0; i < 100000; i++);
}
function foo() {
    delay();
    console.log('foo!'); // 1
}
function bar() {
    delay();
    console.log('bar!'); // 2
}
function baz() {
    delay();
    console.log('baz!'); // 3
}

setTimeout(foo, 10);
setTimeout(bar, 10);
setTimeout(baz, 10);

실행결과) foo! > bar! > baz!
  1. 아무런 지연없이 setTimeout함수가 세번 호출 된 이후 호출 스택이 비워짐
  2. 10ms 후 foo, bar, baz함수가 순차적으로 태스크 큐에 추가 됨
  3. foo함수가 태스크 큐에 들어오자 마자, 호출 스택이 비워있으므로(1번에서 이미 비워짐) foo를 호출 스택에 추가
  4. foo함수의 실행이 끝난 후 호출 스택이 비워지면 이벤트 루프가 다시 큐에서 다음 콜백(bar)를 호출 스택으로 가져와 실행
  5. baz를 4번과 동일한 형태로 실행
  6. 태스크, 태스크 큐가 비어있기 때문에 이벤트 루프는 새로운 태스크가 태스크 큐에 추가 될 때가지 대기하게 됨

웹 브라우저 APIs

  • setTimeout, DOM, AJAX(http 요청) 등등
  • 이벤트 루프와 콜백 큐를 가지고 있음
  • 자바스크립트 자체는 비동기적으로 요청을 처리할 수 없음
  • 자바스크립트 런타임 안에 지원하는 API로 비동기 요청을 처리할 수 있게 함

참고

profile
잘하는것보다 꾸준히하는게 더 중요하다

0개의 댓글