[JSTS-005][기초] Promise와 async·await로 비동기 흐름 읽기
페이지 정보

본문
[이번 수업]
비동기(asynchronous)는 파일·타이머·네트워크처럼 결과가 나중에 준비되는 작업입니다. Promise와 `async`·`await`로 성공·실패, 순서, 동시 실행을 다룹니다.
[선수지식]
JSTS-001~004의 함수, 배열, 콜백과 이벤트 루프를 알고 `node --version`이 동작해야 합니다.
[학습목표]
1. Promise의 pending·fulfilled·rejected 상태를 설명한다.
2. `async` 함수의 반환값과 `await`의 동작을 이해한다.
3. 순차 실행과 `Promise.all` 동시 실행을 구분한다.
4. 거부된 Promise를 `try/catch/finally`로 처리한다.
[핵심개념]
Promise는 나중 결과를 대신하는 객체입니다. pending(대기)에서 성공하면 fulfilled(이행), 실패하면 rejected(거부)가 되며 두 결과 상태를 settled(결정됨)라고 합니다. `.then()`은 성공, `.catch()`는 실패, `.finally()`는 공통 정리 작업을 연결합니다.
`async function`은 항상 Promise를 반환합니다. `return` 값으로 이행되고 `throw` 오류로 거부됩니다. `await`는 현재 async 함수만 잠시 멈춘 뒤 성공값을 꺼내거나 거부 이유를 던집니다. 이벤트 루프의 다른 작업은 계속됩니다.
앞 결과가 다음 입력이면 차례로 `await`합니다. 독립 작업은 Promise를 먼저 만들고 `Promise.all([...])`로 함께 기다립니다. 모두 성공하면 결과 배열을 주고 하나라도 실패하면 거부됩니다. 작업이 많다면 동시 실행 수를 제한합니다.
[따라하기]
아래 내용을 `async-demo.js`로 저장합니다.
```javascript
const { setTimeout: delay } = require("node:timers/promises");
async function runJob(name, ms, fail = false) {
await delay(ms);
if (fail) throw new Error(`${name} 실패`);
return `${name} 완료`;
}
async function main() {
console.log("시작");
try {
const results = await Promise.all([
runJob("A", 100),
runJob("B", 50),
]);
console.log(results.join(", "));
await runJob("C", 10, true);
} catch (error) {
console.log("오류:", error.message);
} finally {
console.log("정리");
}
}
main();
```
Windows PowerShell·명령 프롬프트와 macOS·Linux 터미널에서 실행 명령은 같습니다.
```shell
node async-demo.js
```
예상 결과:
```text
시작
A 완료, B 완료
오류: C 실패
정리
```
B가 먼저 끝나도 결과 배열은 입력 순서인 A, B입니다. C의 오류는 catch가 처리하고 finally는 항상 실행됩니다. `delay`는 Node.js 내장 Promise 타이머입니다.
[흔한 실수]
`await`를 빼면 완료값 대신 Promise가 보일 수 있고, 반환된 Promise의 실패를 처리하지 않으면 처리되지 않은 거부가 생깁니다. Promise를 반환하는 API를 `new Promise`로 다시 감싸지 마세요. 독립 작업을 하나씩 await하면 느려지고 의존 작업을 동시에 시작하면 순서가 깨집니다. `forEach`는 async 콜백 완료를 기다리지 않으므로 Promise 배열과 `Promise.all`을 사용합니다.
[보안 주의]
외부 요청에는 제한 시간과 취소 수단을 두고 지원 API에는 `AbortSignal`을 전달합니다. 응답의 형식과 권한을 검증하고, 오류 객체나 요청 헤더를 그대로 출력해 토큰·개인정보를 노출하지 마세요. 대량 Promise와 재시도에는 상한을 둡니다.
[직접 해볼 과제]
1. A와 B를 차례로 await하도록 바꿔 실행 순서와 걸린 시간을 `console.time`으로 비교하세요.
2. `Promise.all`의 B 작업도 실패하게 만든 뒤 catch가 받는 첫 거부 이유를 확인하세요.
[확인문제]
1. Promise의 세 상태와 settled가 뜻하는 상태는 무엇인가요?
2. `await`가 기다리는 동안 JavaScript 전체 실행이 멈추나요?
3. 서로 독립적인 두 작업에 `Promise.all`을 쓰는 이유는 무엇인가요?
[다음 학습]
JSTS-006에서는 npm과 모듈 시스템으로 외부 패키지와 프로젝트 의존성을 관리합니다.
[공식 참고 자료]
ECMAScript Promise 표준: https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-promise-objects
ECMAScript async 함수 표준: https://tc39.es/ecma262/multipage/ecmascript-language-functions-and-classes.html#sec-async-function-definitions
MDN Promise 참고: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Node.js Promise 타이머: https://nodejs.org/api/timers.html
비동기(asynchronous)는 파일·타이머·네트워크처럼 결과가 나중에 준비되는 작업입니다. Promise와 `async`·`await`로 성공·실패, 순서, 동시 실행을 다룹니다.
[선수지식]
JSTS-001~004의 함수, 배열, 콜백과 이벤트 루프를 알고 `node --version`이 동작해야 합니다.
[학습목표]
1. Promise의 pending·fulfilled·rejected 상태를 설명한다.
2. `async` 함수의 반환값과 `await`의 동작을 이해한다.
3. 순차 실행과 `Promise.all` 동시 실행을 구분한다.
4. 거부된 Promise를 `try/catch/finally`로 처리한다.
[핵심개념]
Promise는 나중 결과를 대신하는 객체입니다. pending(대기)에서 성공하면 fulfilled(이행), 실패하면 rejected(거부)가 되며 두 결과 상태를 settled(결정됨)라고 합니다. `.then()`은 성공, `.catch()`는 실패, `.finally()`는 공통 정리 작업을 연결합니다.
`async function`은 항상 Promise를 반환합니다. `return` 값으로 이행되고 `throw` 오류로 거부됩니다. `await`는 현재 async 함수만 잠시 멈춘 뒤 성공값을 꺼내거나 거부 이유를 던집니다. 이벤트 루프의 다른 작업은 계속됩니다.
앞 결과가 다음 입력이면 차례로 `await`합니다. 독립 작업은 Promise를 먼저 만들고 `Promise.all([...])`로 함께 기다립니다. 모두 성공하면 결과 배열을 주고 하나라도 실패하면 거부됩니다. 작업이 많다면 동시 실행 수를 제한합니다.
[따라하기]
아래 내용을 `async-demo.js`로 저장합니다.
```javascript
const { setTimeout: delay } = require("node:timers/promises");
async function runJob(name, ms, fail = false) {
await delay(ms);
if (fail) throw new Error(`${name} 실패`);
return `${name} 완료`;
}
async function main() {
console.log("시작");
try {
const results = await Promise.all([
runJob("A", 100),
runJob("B", 50),
]);
console.log(results.join(", "));
await runJob("C", 10, true);
} catch (error) {
console.log("오류:", error.message);
} finally {
console.log("정리");
}
}
main();
```
Windows PowerShell·명령 프롬프트와 macOS·Linux 터미널에서 실행 명령은 같습니다.
```shell
node async-demo.js
```
예상 결과:
```text
시작
A 완료, B 완료
오류: C 실패
정리
```
B가 먼저 끝나도 결과 배열은 입력 순서인 A, B입니다. C의 오류는 catch가 처리하고 finally는 항상 실행됩니다. `delay`는 Node.js 내장 Promise 타이머입니다.
[흔한 실수]
`await`를 빼면 완료값 대신 Promise가 보일 수 있고, 반환된 Promise의 실패를 처리하지 않으면 처리되지 않은 거부가 생깁니다. Promise를 반환하는 API를 `new Promise`로 다시 감싸지 마세요. 독립 작업을 하나씩 await하면 느려지고 의존 작업을 동시에 시작하면 순서가 깨집니다. `forEach`는 async 콜백 완료를 기다리지 않으므로 Promise 배열과 `Promise.all`을 사용합니다.
[보안 주의]
외부 요청에는 제한 시간과 취소 수단을 두고 지원 API에는 `AbortSignal`을 전달합니다. 응답의 형식과 권한을 검증하고, 오류 객체나 요청 헤더를 그대로 출력해 토큰·개인정보를 노출하지 마세요. 대량 Promise와 재시도에는 상한을 둡니다.
[직접 해볼 과제]
1. A와 B를 차례로 await하도록 바꿔 실행 순서와 걸린 시간을 `console.time`으로 비교하세요.
2. `Promise.all`의 B 작업도 실패하게 만든 뒤 catch가 받는 첫 거부 이유를 확인하세요.
[확인문제]
1. Promise의 세 상태와 settled가 뜻하는 상태는 무엇인가요?
2. `await`가 기다리는 동안 JavaScript 전체 실행이 멈추나요?
3. 서로 독립적인 두 작업에 `Promise.all`을 쓰는 이유는 무엇인가요?
[다음 학습]
JSTS-006에서는 npm과 모듈 시스템으로 외부 패키지와 프로젝트 의존성을 관리합니다.
[공식 참고 자료]
ECMAScript Promise 표준: https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-promise-objects
ECMAScript async 함수 표준: https://tc39.es/ecma262/multipage/ecmascript-language-functions-and-classes.html#sec-async-function-definitions
MDN Promise 참고: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Node.js Promise 타이머: https://nodejs.org/api/timers.html
- 이전글[WEB-005][기초] DOM을 찾고 클릭 이벤트로 화면 바꾸기 26.09.01
- 다음글[PY-005][기초] 가상환경과 pip로 패키지 따로 관리하기 26.08.31
댓글목록
등록된 댓글이 없습니다.
