From 378a653f99723e96eabdac9aca146cacdf1b9dc2 Mon Sep 17 00:00:00 2001 From: "DESKTOP-PDMTIQO\\hansu" Date: Thu, 25 Jan 2024 19:53:28 +0900 Subject: [PATCH] =?UTF-8?q?:memo:=20docs:=2042=EC=9E=A5=20=EB=B9=84?= =?UTF-8?q?=EB=8F=99=EA=B8=B0=20=ED=94=84=EB=A1=9C=EA=B7=B8=EB=9E=98?= =?UTF-8?q?=EB=B0=8D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\355\225\234\354\210\230\354\247\200.md" | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 "docs/42_\353\271\204\353\217\231\352\270\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\234\354\210\230\354\247\200.md" diff --git "a/docs/42_\353\271\204\353\217\231\352\270\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\234\354\210\230\354\247\200.md" "b/docs/42_\353\271\204\353\217\231\352\270\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\234\354\210\230\354\247\200.md" new file mode 100644 index 00000000..582016a3 --- /dev/null +++ "b/docs/42_\353\271\204\353\217\231\352\270\260 \355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/\355\225\234\354\210\230\354\247\200.md" @@ -0,0 +1,142 @@ +## 42장. ✨ 비동기 프로그래밍 + +### 📌 42-1. 동기 처리와 비동기 처리 + +> `함수의 실행 순서는 실행 컨텍스트 스택으로 관리`하며, **자바스크립트 엔진은 단 하나의 실행 컨텍스트 스택**을 갖습니다. + +함수를 호출하면, 함수 코드가 평가되어 함수 실행 컨텍스트가 생성됩니다. + +이때 생성된 함수 실행 컨텍스트는 실행 컨텍스트 스택(= 콜스택)에 푸쉬되고 함수코드가 실행됩니다. + +함수 코드의 실행이 종료하면 함수 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거됩니다. + +```js +const foo () => {}; +const bar () => {}; + +foo(); +bar(); +``` + +![](https://velog.velcdn.com/images/ninto_2/post/b3129d02-5de0-4ecd-b37a-9fb2557fe7c2/image.png) + +위와 같이 실행 컨텍스트 스택은 LIFO (Last In First Out) 방식으로 가장 늦게 들어온 함수 컨텍스트가 가장 먼저 나가는 구조를 가지고 있습니다. + +**실행 컨텍스트 스택에 함수 실행 컨텍스트가 푸시되는것은 함수 실행의 시작**을 의미합니다. + +실행 컨텍스트 스택의 최상위 요소인 `실행 중인 실행 컨텍스트`를 `제외한 모든 실행 컨텍스트는 모두 실행 대기 중인 태스크` 들입니다. + +> 이처럼, **자바스크립트 엔진은 한번에 하나의 태스크만 실행할 수 있는 싱글 스레드 방식**으로 동작합니다. + +**싱글 스레드 방식**에선, `한 번에 하나의 태스크만 실행` 할 수 있기 때문에 **처리에 시간이 걸리는 태스크를 실행하는 경우 블로킹(= 작업중단)이 발생**하게 됩니다. + +> `현재 실행 중인 태스크가 종료될 때까지 다음에 실행될 태스크가 대기`하는 방식을 `동기(synchronous)처리` 라고 합니다. + +**동기 처리 방식은 태스크를 순서대로 하나씩 처리**하므로, **실행 순서가 보장**은 되지만 **앞선 태스크가 종료할 때까지 다른 태스크들은 블로킹**된다는 단점을 가지고 있습니다. + +```js +function foo() { + console.log("foo"); +} + +function bar() { + console.log("bar"); +} + +// setTimeout은 일정 시간이 경과한 이후, 콜백 함수 foo를 호출합니다. +// setTimeout은 bar 함수를 블로킹하지 않습니다. +setTimeout(foo, 3 * 1000); +bar(); +``` + +위 코드를 살펴보면, setTimeout 함수 이후의 태스크를 블로킹하지 않고 곧바로 실행합니다. + +![](https://velog.velcdn.com/images/ninto_2/post/cd909334-a78e-4dcb-a188-d4c52ccc8691/image.png) + +> 이처럼 `현재 실행중인 태스크가 종료되지 않은 상태라 해도, 다음 태스크를 곧바로 실행`하는 방식을 `비동기(asynchronous) 처리`라고 합니다. + +`비동기 처리 방식`은, **다음 태스크를 곧바로 실행하므로 블로킹이 발생하지 않는다**는 장점을 가지지만, **태스크의 실행 순서가 보장되지 않는다**는 단점을 가집니다. + +비동기 처리를 수행하는 `비동기 함수`는 전통적으로 `콜백 패턴을 사용`합니다. + +![](https://velog.velcdn.com/images/ninto_2/post/22369bf8-354a-4b18-af3b-0915ea670401/image.png) + +하지만, 이 **콜백 패턴은 콜백 헬을 발생시켜 가독성을 나쁘게하고, 비동기 처리 중 발생한 예러의 예외 처리가 곤란하며, 여러개의 비동기 처리를 한 번에 처리하는데도 한계**가 있습니다. + +이를 보완하기 위해, `Promise와 같은 비동기 함수가 등장`하였습니다. + +추가적으로, **타이머 함수인 setTimeout과 setInterval, HTTP 요청, 이벤트 핸들러는 비동기 처리 방식**으로 동작합니다. + +
+ +--- + +### 📌 42-2. 이벤트 루프와 태스크 큐 + +앞서 살펴본 것 처럼, **자바스크립트는 싱글 스레드로 동작**합니다. + +- 싱글 스레드 : 한 번에 하나의 태스크만 처리 가능 + +하지만 브라우저가 동작하는 것을 살펴보면 많은 태스크가 동시에 처리되는 것 처럼 느껴집니다. + +ex. HTML 요소가 애니메이션을 통해 움직이면서 이벤트 처리, HTTP 요청을 통해 서버로부터 데이터를 가지고 오면서 렌더링 등... + +> `이벤트 루프`는 **자바스크립트의 동시성을 지원**합니다. + +이벤트 루프는 브라우저에 내장되어 있는 기능 중 하나입니다. + +![](https://velog.velcdn.com/images/ninto_2/post/ab2951d5-def5-418d-880d-7dfceb6eace6/image.png) + +구글의 V8 자바스크립트 엔진을 비롯한 `대부분의 자바스크립트 엔진은 크게 콜스택과 힙이라는 2개의 영역으로 구분`할 수 있습니다. + +#### 🔎 1. 콜스택 (Call Stack) = 실행 컨텍스트 스택 + +`소스코드(전역 코드나 함수 코드 등) 평가 과정에서 생성된 실행 컨텍스트가 추가되고, 제거되는 스택 자료구조`인 실행 컨텍스트 스택입니다. + +함수를 호출하면 함수 실행 컨텍스트가 **순차적으로 콜 스택에 푸시되어 순차적으로 실행**됩니다. + +자바스크립트 엔진은 하나의 콜 스택을 사용하기 때문에, 최상위 실행 컨텍스트가 종료되어 콜 스택에서 제거되기 전까지는 다른 어떤 태스크도 실행되지 않습니다. (블로킹) + +#### 🔎 2. 힙 (Heap) + +힙은 `객체가 저장되는 메모리 공간`입니다. + +콜 스택의 요소인 **실행 컨텍스트는 힙에 저장된 객체를 참조**합니다. + +메모리에 값을 저장하려면 먼저 값을 저장할 메모리 공간의 크기를 결정해야 합니다. + +객체는 원시 값과는 달리 크기가 정해져 있지 않기 때문에, 할당해야 할 `메모리 공간의 크기를 런타임에 결정`해야 합니다. (= `동적 할당`) + +따라서, 객체가 저장되는 메모리 공간인 **힙은 구조화 되어있지 않다**는 특징이 있습니다. + +`콜 스택과 힙으로 구성되어 있는 자바스크립트 엔진`은 `단순히 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 실행`할 뿐입니다. + +비동기 처리에서 소스코드의 평가와 실행을 제외한 모든 처리는 자바스크립트 엔진을 구동하는 환경인 브라우저 또는 Node.js가 담당합니다. + +> 이를 위해, `브라우저 환경은 태스크 큐와 이벤트 루프를 제공`합니다. + +#### 🔎 3. 태스크 큐 (task queue) + +`setTimeout`이나 `setInterval`과 같은 **비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역**입니다. + +참고로, 프로미스의 후속 처리 메서드의 콜백 함수가 일시적으로 보관되는 마이크로태스크 큐도 존재합니다. + +#### 🔎 4. 이벤트 루프 (event loop) + +`콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지`, 그리고 `태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지` `반복해서 확인`합니다. + +만약 **콜 스택이 비어있고, 태스크 큐에 대기 중인 함수가 있는 상황**이라면 **이벤트 루프는 순차적(FIFO, first in First Out, 큐)으로 태스크 큐에 대기 중인 함수를 콜 스택으로 이동**시킵니다. + +이때 콜 스택으로 이동한 함수는 실행이 됩니다. + +즉, `태스크 큐에 일시 보관된 함수들은 비동기 처리 방식으로 동작`합니다. + +> `자바스크립트 엔진은 싱글 스레드 방식`으로 동작하지만, `브라우저 환경은 멀티 스레드`로 동작합니다. + +만약 모든 자바스크립트 코드가 자바스크립트 엔진에서 싱글 스레드 방식으로 동작한다면 자바스크립트는 비동기 동작할 수 없습니다. + +이처럼, **브라우저 환경이 멀티 스레드 방식으로 이벤트 루프와 태스크 큐를 통해 비동기 동작을 지원**하기 때문에 **자바스크립트 코드에서 비동기 프로그래밍이 가능**해졌습니다. + +이러한 구조 덕분에 브라우저는 여러 작업을 동시에 처리하고, 웹 페이지가 응답성을 유지하면서도 비동기 프로그래밍이 가능해졌습니다. + +자바스크립트에서는 `비동기 프로그래밍`을 위해 주로 `콜백 함수, Promise, async/await 등의 패턴을 사용`합니다.