Skip to content

Commit

Permalink
📝 docs: 42장 비동기 프로그래밍 정리
Browse files Browse the repository at this point in the history
  • Loading branch information
nincoding committed Jan 25, 2024
1 parent 04c653e commit 378a653
Showing 1 changed file with 142 additions and 0 deletions.
142 changes: 142 additions & 0 deletions docs/42_비동기 프로그래밍/한수지.md
Original file line number Diff line number Diff line change
@@ -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 요청, 이벤트 핸들러는 비동기 처리 방식**으로 동작합니다.

<br>

---

### 📌 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 등의 패턴을 사용`합니다.

0 comments on commit 378a653

Please sign in to comment.