[JSTS-004][기초] 이벤트 루프로 비동기 실행 순서 이해하기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[JSTS-004][기초] 이벤트 루프로 비동기 실행 순서 이해하기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 265회 작성일 26-08-31 04:33

본문

[이번 수업]
JavaScript 코드는 위에서 아래로 읽히지만 타이머와 Promise의 출력은 작성 순서와 다를 수 있습니다. 이벤트 루프는 실행할 일을 큐에서 가져와 JavaScript가 처리하도록 연결합니다.

[선수지식]
JSTS-001의 실행 환경과 기본 문법, JSTS-002의 함수·스코프, JSTS-003의 배열·객체를 알면 좋습니다. 터미널에서 `node --version`이 실행되어야 합니다.

[학습목표]
1. 호출 스택과 이벤트 루프, 작업 큐의 역할을 설명한다.
2. 동기 코드·마이크로태스크·타이머의 실행 순서를 예측한다.
3. `setTimeout(..., 0)`이 즉시 실행을 뜻하지 않음을 이해한다.
4. 긴 동기 작업과 처리되지 않은 Promise 오류를 피한다.

[핵심개념]
호출 스택(call stack)은 지금 실행 중인 함수가 쌓이는 곳입니다. 한 함수가 끝나야 그 아래 작업으로 돌아갑니다. 일반 JavaScript 문장은 현재 스택에서 동기적으로 실행되므로 앞 문장이 끝나기 전에는 다음 문장이 실행되지 않습니다.

타이머·네트워크·파일 입출력은 실행 환경이 관리합니다. 준비된 콜백은 바로 현재 함수를 끊고 들어오는 것이 아니라, 실행 가능한 큐에 놓였다가 스택이 비었을 때 처리됩니다. 이 과정을 계속 조정하는 실행 모델을 이벤트 루프라고 부릅니다.

작업(task)은 타이머, 사용자 입력 같은 일을 처리하는 단위입니다. 마이크로태스크(microtask)는 Promise 반응처럼 현재 작업이 끝난 뒤 다음 작업으로 넘어가기 전에 처리되는 더 짧은 후속 작업입니다. 예제에서는 전체 스크립트가 먼저 끝나고 Promise의 `then`이 실행된 다음 타이머 콜백이 실행됩니다.

`setTimeout(callback, 0)`의 0은 즉시 실행 명령이 아니라 최소 지연 요청에 가깝습니다. 현재 스택과 먼저 처리할 작업이 끝나야 콜백이 실행되므로 실제 시간은 더 늦을 수 있습니다. 브라우저는 렌더링과 입력 작업을 함께 다루고, Node.js는 libuv 기반 단계로 입출력과 타이머를 처리합니다. 환경별 세부 순서에 기대기보다 필요한 순서는 `await`나 Promise 연결로 명시합니다.

[따라하기]
아래 내용을 event-loop.js로 저장합니다.

```javascript
console.log('1: 동기 시작');

setTimeout(() => {
  console.log('4: 타이머 작업');
}, 0);

Promise.resolve().then(() => {
  console.log('3: Promise 마이크로태스크');
});

console.log('2: 동기 끝');
```

Windows PowerShell, macOS, Linux 모두 Node.js가 설치되어 있으면 `node event-loop.js`로 실행합니다. 예상 결과는 다음과 같습니다.

```text
1: 동기 시작
2: 동기 끝
3: Promise 마이크로태스크
4: 타이머 작업
```

첫 번째와 마지막 `console.log`는 같은 스크립트 작업에서 동기 실행됩니다. 그 뒤 Promise 반응이 마이크로태스크로 처리되고, 타이머 콜백은 이후 작업으로 실행됩니다.

[흔한 실수]
- 비동기를 여러 CPU 코어에서 자동 병렬 실행되는 것으로 생각합니다.
- `setTimeout(..., 0)`을 정확히 0밀리초 뒤 실행된다는 보장으로 봅니다.
- Promise를 만들기만 하면 긴 계산이 스레드를 막지 않는다고 생각합니다. 계산 자체가 동기라면 이벤트 루프를 막습니다.
- `then`이나 `await` 없이 비동기 결과를 바로 읽으려 합니다. 완료 시점을 코드로 연결하세요.

[보안 주의]
외부 요청에는 제한 시간과 취소 방법을 두고, 동시 작업 수와 입력 크기를 제한해 자원 고갈을 막으세요. Promise 거부를 비워 둔 `catch`로 숨기지 말고 안전한 메시지와 필요한 로그를 남깁니다. 오류 로그에 토큰·쿠키·개인정보를 넣지 않습니다. 사용자 입력으로 무제한 타이머나 마이크로태스크를 생성하지 말고, CPU를 오래 쓰는 작업은 작업 분할이나 Worker를 검토합니다. 실습은 로컬의 고정 문자열만 출력합니다.

[직접 해볼 과제]
1. Promise `then`을 하나 더 연결하고 두 마이크로태스크의 순서를 기록하세요.
2. 타이머 두 개를 등록하되 정확한 실행 시각을 가정하지 말고 관찰 결과를 적으세요.
3. 각 로그 앞에 `Date.now()`를 붙여 순서와 실제 지연 시간이 다른 개념임을 확인하세요.

[확인문제]
1. 호출 스택이 비기 전에 타이머 콜백이 실행되지 않는 이유는 무엇인가요?
2. 이 예제에서 Promise 출력이 타이머보다 먼저 나오는 이유는 무엇인가요?
3. 긴 동기 계산이 비동기 입출력 응답까지 늦추는 이유는 무엇인가요?

[다음 학습]
번호 우선 순환에 따라 다음 글은 WEB-004 웹 접근성과 키보드 사용입니다. JSTS 다음 수업은 JSTS-005 Promise와 async·await입니다.

[공식 참고 자료]
- WHATWG HTML 이벤트 루프: https://html.spec.whatwg.org/multipage/webappapis.html#event-loops
- ECMAScript Jobs와 Job Queues: https://tc39.es/ecma262/multipage/executable-code-and-execution-contexts.html#sec-jobs-and-job-queues
- Node.js 이벤트 루프: https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick
- Node.js timers: https://nodejs.org/api/timers.html#settimeoutcallback-delay-args

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,831
어제
6,862
최대
16,772
전체
770,782
Copyright © 소유하신 도메인. All rights reserved.