비동기 제너레이터 (Async Generators)
자바스크립트에서 비동기 작업을 순차적으로 생성하며 처리하려면 비동기 제너레이터가 유용하다. 이는 비동기 이터레이터를 더 간결하게 구현할 수 있게 해준다. 이번에는 비동기 제너레이터의 기본부터 심화까지 코드와 함께 자세히 풀어보려고 한다.
비동기 제너레이터를 잘 다루면 비동기 데이터 흐름을 깔끔하고 효율적으로 관리할 수 있다. 단계별로 하나씩 살펴보자.
비동기 제너레이터 기본
async function*
로 정의하며, yield
가 비동기 값을 생성한다:
async function* asyncGenerator() {
yield Promise.resolve(1);
yield Promise.resolve(2);
yield Promise.resolve(3);
}
async function process() {
const gen = asyncGenerator();
for await (const num of gen) {
console.log(num);
}
}
process();
// 1
// 2
// 3
for await...of
로 비동기 제너레이터를 순회하며 값을 받았다. Promise가 자동으로 해결된다.
1. 비동기 작업과 yield 결합
시간 지연을 포함한 비동기 작업을 생성해보자:
function delay(ms, value) {
return new Promise((resolve) => {
setTimeout(() => resolve(value), ms);
});
}
async function* asyncGenerator() {
yield delay(1000, "첫 번째");
yield delay(1000, "두 번째");
yield delay(1000, "세 번째");
}
async function process() {
for await (const value of asyncGenerator()) {
console.log(value);
}
}
process();
// 1초 후 "첫 번째"
// 2초 후 "두 번째"
// 3초 후 "세 번째"
각 yield
가 비동기 작업을 기다리며 순차적으로 값을 생성했다.
2. 외부 API 데이터 생성
API 호출을 비동기 제너레이터로 처리해보자:
async function* fetchPosts() {
for (let id = 1; id <= 3; id++) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
const data = await response.json();
yield data.title;
}
}
async function process() {
for await (const title of fetchPosts()) {
console.log(title);
}
}
process();
// "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"
// "qui est esse"
// "ea molestias quasi exercitationem repellat qui ipsa sit aut"
API에서 가져온 데이터를 하나씩 yield
로 생성하며 순회했다.
3. 에러 처리
비동기 제너레이터에서도 에러를 관리할 수 있다:
async function* asyncGenerator() {
yield delay(1000, 1);
throw new Error("에러 발생");
yield delay(1000, 3);
}
async function process() {
try {
for await (const num of asyncGenerator()) {
console.log(num);
}
} catch (error) {
console.log("에러: " + error.message);
}
}
process();
// 1초 후 1
// "에러: 에러 발생"
throw
로 에러를 발생시키고, try-catch
로 잡아서 처리했다.
4. 입력값 기반 생성
외부 입력을 받아 동적으로 값을 생성할 수 있다:
async function* countGenerator(max) {
for (let i = 1; i <= max; i++) {
yield delay(1000, i);
}
}
async function process() {
for await (const num of countGenerator(3)) {
console.log(num);
}
}
process();
// 1초 후 1
// 2초 후 2
// 3초 후 3
매개변수로 받은 최대값까지 비동기적으로 생성했다.
5. 스트림처럼 활용
비동기 제너레이터를 스트림처럼 사용할 수 있다:
async function* streamGenerator() {
let count = 0;
while (count < 5) {
count++;
yield delay(500, `스트림 ${count}`);
}
}
async function processStream() {
for await (const chunk of streamGenerator()) {
console.log(chunk);
}
}
processStream();
// 0.5초 후 "스트림 1"
// 1초 후 "스트림 2"
// 1.5초 후 "스트림 3"
// 2초 후 "스트림 4"
// 2.5초 후 "스트림 5"
지속적인 데이터 흐름을 시뮬레이션하며 순차적으로 값을 생성했다.
6. 조기 종료와 return
제너레이터를 조기에 종료하고 정리할 수 있다:
async function* asyncGenerator() {
try {
yield delay(1000, 1);
yield delay(1000, 2);
yield delay(1000, 3);
} finally {
console.log("제너레이터 종료");
}
}
async function process() {
const gen = asyncGenerator();
for await (const num of gen) {
console.log(num);
if (num === 2) {
await gen.return();
break;
}
}
}
process();
// 1초 후 1
// 2초 후 2
// "제너레이터 종료"
return
메서드로 종료하고, finally
로 정리 작업을 실행했다.
7. next()로 수동 제어
for await...of
대신 next()
로 수동으로 제어할 수 있다:
async function* asyncGenerator() {
yield delay(1000, 1);
yield delay(1000, 2);
yield delay(1000, 3);
}
async function processManual() {
const gen = asyncGenerator();
let result = await gen.next();
while (!result.done) {
console.log(result.value);
result = await gen.next();
}
}
processManual();
// 1초 후 1
// 2초 후 2
// 3초 후 3
수동으로 next()
를 호출해서 값을 하나씩 처리했다.
8. 성능과 가독성에 미치는 영향
비동기 제너레이터가 코드에 어떤 영향을 주는지 보자:
- 성능: 비동기 작업을 순차적으로 처리하니 대기 시간이 늘어날 수 있지만, 필요한 만큼만 생성해서 효율적이다.
- 가독성: yield
와 async
조합으로 비동기 흐름이 명확해진다.
yield로 비동기 값을 간결하게 생성하고, for await로 쉽게 순회하는 점이 핵심이다.
마무리
비동기 제너레이터는 비동기 데이터 생성과 순회를 단순화한다. 기본 사용부터 API 처리, 스트림, 에러 관리까지 다양한 상황에서 유연하게 활용할 수 있다.
'코딩 공부 > 자바스크립트' 카테고리의 다른 글
65. 자바스크립트 이벤트 루프와 태스크 스케줄링 (Event Loop and Task Scheduling) (0) | 2025.03.21 |
---|---|
64. 자바스크립트 비동기 패턴 심화 (Advanced Async Patterns) (1) | 2025.03.21 |
62. 자바스크립트 비동기 이터레이터 (Async Iterators) (1) | 2025.03.20 |
61. 자바스크립트 에러 로깅과 모니터링 (Error Logging and Monitoring) (1) | 2025.03.20 |
60. 자바스크립트 디버깅 도구 활용 (Using Debugging Tools) (2) | 2025.03.20 |