공부/frontend

Generator Function과 async/await: 차이점과 사용법

sesam 2025. 11. 2. 22:27
728x90

 

비유로 이해하기
Generator (function*): 책을 읽다가 책갈피를 넣고 나중에 그 자리부터 다시 읽는 것
async/await: 요리를 하며 각 단계가 끝날 때까지 기다리는 것


1. Generator Function (function*)이란?
Generator는 값을 하나씩 생산하는 함수입니다.

// 일반 함수
function getNumbers() {
    return [1, 2, 3, 4, 5]; // 한 번에 모든 값을 반환
}

// Generator 함수
function* getNumbersOneByOne() {
    yield 1;  // 첫 번째 값을 반환하고 멈춤
    yield 2;  // 두 번째 값을 반환하고 멈춤
    yield 3;  // 세 번째 값을 반환하고 멈춤
    yield 4;
    yield 5;
}

 

 

 

실제 사용:

const generator = getNumbersOneByOne();

console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: 4, done: false }
console.log(generator.next()); // { value: 5, done: false }
console.log(generator.next()); // { value: undefined, done: true }

 

2. async/await란?
비동기 작업을 순차적으로 처리하는 문법입니다.

// Promise를 사용한 방법 (구식)
function fetchUser() {
    return fetch('/api/user')
        .then(response => response.json())
        .then(user => {
            return fetch('/api/posts')
                .then(response => response.json())
                .then(posts => ({ user, posts }));
        });
}

// async/await를 사용한 방법 (최신)
async function fetchUser() {
    const userResponse = await fetch('/api/user');
    const user = await userResponse.json();
    
    const postsResponse = await fetch('/api/posts');
    const posts = await postsResponse.json();
    
    return { user, posts };
}

 

 

3. 자주 하는 실수: yield vs await
❌ 잘못된 코드

async function getData() {
    const result = yield fetch('/api/data'); // ❌ 오류!
    // "A 'yield' expression is only allowed in a generator body"
}

이유: async 함수에서는 await를 써야 합니다.

 

✅ 올바른 코드

async function getData() {
    const response = await fetch('/api/data'); // ✅ 올바름!
    const result = await response.json();
    return result;
}

 

 

4. Generator를 비동기와 함께 사용하려면?
Generator를 비동기와 함께 쓰려면 아래처럼 해야 하지만, 대개는 async/await가 더 간단합니다.

async function* fetchData() {
    yield await fetch('/api/user');
    yield await fetch('/api/posts');
}

// 사용하기 복잡함
const gen = fetchData();
const user = await gen.next();
const posts = await gen.next();

 

 

5. 언제 무엇을 사용할까?

 

 

6. 실제 비교 예시
시나리오: 사용자 정보와 게시글을 가져오기

// ❌ 잘못된 방법
async function getUserData() {
    const user = yield fetch('/api/user');      // 오류!
    const posts = yield fetch('/api/posts');    // 오류!
    return { user, posts };
}

// ✅ 올바른 방법
async function getUserData() {
    const userResponse = await fetch('/api/user');
    const user = await userResponse.json();
    
    const postsResponse = await fetch('/api/posts');
    const posts = await postsResponse.json();
    
    return { user, posts };
}

// 또는 Promise.all로 동시에 처리
async function getUserData() {
    const [userResponse, postsResponse] = await Promise.all([
        fetch('/api/user'),
        fetch('/api/posts')
    ]);
    
    const user = await userResponse.json();
    const posts = await postsResponse.json();
    
    return { user, posts };
}

 

 

핵심 정리
yield: Generator (function*) 안에서만 사용
await: async 함수 안에서만 사용
비동기 작업은 보통 async/await 사용
Generator는 반복자나 값 생성에 주로 사용

 


기억할 점
> "async 함수에는 await, generator 함수에는 yield"
이 문장만 기억해도 대부분의 실수를 피할 수 있습니다.

 

 

 

 


 

Q. 왜 Generator라고 부르는지?

A.

Generator(제너레이터) 는 JavaScript의 “값을 하나씩(지연해서) 만들어 내는 함수”이다.

필요할 때마다 다음 값을 “생산(generate)”해서 넘겨주는 함수적 동작을 의미한다.

즉, Generator는 말 그대로 “값을 생성해주는 기계”예요.

 

🔁 일반 함수 vs Generator 함수의 차이

구분일반 함수Generator 함수
실행 한 번 호출하면 끝까지 실행됨 중간에 멈췄다가 다시 이어서 실행 가능
반환 한 번만 return 가능 여러 번 yield로 값을 하나씩 반환 가능
메모리 전체 결과를 한꺼번에 만듦 요청할 때마다 하나씩 만들어냄 (지연 생성, lazy evaluation)

 

🧠 “값을 하나씩 만들어낸다”는 의미

예를 들어, 1부터 1000000까지 숫자를 만든다고 해볼게요.

(1) 일반 함수

function makeList() {
  const arr = [];
  for (let i = 1; i <= 1000000; i++) arr.push(i);
  return arr;
}
const list = makeList(); // 이미 백만개 숫자를 한 번에 만듦 → 메모리 많이 사용

➡️ 모든 값을 한 번에 “생성 완료”해야 함.

 

(2) Generator 함수

function* makeNumbers() {
  for (let i = 1; i <= 1000000; i++) yield i;
}
const gen = makeNumbers();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
➡️ next()를 호출할 때마다 필요한 값만 즉석에서 생성
➡️ 다음 요청이 오기 전까지는 멈춰 있음.
➡️ 그래서 “값을 하나씩 만들어낸다(generate)”고 부르는 거예요.
 
 
 

🪄 비유로 말하자면

  • 일반 함수: 공장에서 한 번에 백만 개 제품을 다 만들어 창고에 쌓아두는 방식
  • Generator: 주문이 들어올 때마다 제품을 하나씩 즉석에서 만들어주는 방식

즉, Generator는 필요할 때마다 즉석에서 값을 생산하는 함수예요.
이 “지연 생성(lazy generation)” 개념이 바로 “값을 하나씩 만들어낸다”의 핵심 의미예요

 
 
728x90