자바스크립트 제너레이터

자바스크립트는 많은 언어에서 사용되는 동적 언어로서, 함수를 생성하는 다양한 방법을 제공합니다. 이 중에서도 제너레이터 함수는 다른 함수와는 조금 다른 특별한 동작 방식을 갖고 있어서 많은 개발자들에게 인기를 끌고 있습니다. 제너레이터 함수는 이터레이터(iterator)를 사용하여 값을 생성하는 함수입니다. 이번 글에서는 자바스크립트 제너레이터에 대해 자세히 알아보고, 제너레이터를 사용하여 다양한 작업을 수행하는 방법을 소개하겠습니다.

제너레이터 함수란?

제너레이터 함수는 function* 키워드를 사용하여 정의되며, 함수 내부의 실행 흐름을 중지하고 재개할 수 있는 기능을 제공합니다. 이 기능은 함수가 여러 번 실행되고 중간에 값을 반환한 다음 다시 실행될 수 있도록 합니다.

아래는 간단한 제너레이터 함수의 예제입니다.

function* counter() {
  let count = 0;
  while (true) {
    yield count++;
  }
}

const iterator = counter();

console.log(iterator.next().value); // 0
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2

위의 예제에서 counter 제너레이터 함수는 yield 키워드를 사용하여 값을 반환합니다. yield가 실행되면 함수의 상태는 중단되며, 다음 호출 시에는 중단된 부분부터 다시 실행됩니다. iterator.next()를 호출하여 제너레이터 함수를 호출하고, .value를 통해 반환된 값을 확인할 수 있습니다.

제너레이터 함수의 활용 방법

제너레이터 함수는 단순히 값을 생성하는 기능 뿐만 아니라 다양한 작업에 활용될 수 있습니다.

1. 이터러블 객체 생성

제너레이터 함수는 이터레이터(iterator)를 반환하는 특성을 가지기 때문에, 이터러블 객체를 생성하기에 아주 유용합니다. 이터러블 객체는 Symbol.iterator 메소드를 구현하여 for...of 루프와 같은 문법적 구조에서 값을 순회할 수 있는 객체입니다.

아래는 제너레이터 함수를 이용하여 이터러블 객체를 생성하는 예제입니다.

function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const seq = fibonacci();
for (const number of seq) {
  if (number > 100) {
    break;
  }
  console.log(number);
}

위의 예제에서 fibonacci 제너레이터 함수는 피보나치 수열을 생성합니다. for...of 루프를 통해 제너레이터가 반환하는 값을 순회하고, 조건에 따라 순회를 중지할 수 있습니다.

2. 비동기 연산 처리

제너레이터 함수는 비동기 연산을 처리하는 데에도 유용합니다. yield 키워드를 통해 비동기 연산의 결과를 반환하고, 이후에 해당 결과를 처리하는 로직을 작성할 수 있습니다. 이를 통해 콜백 헬을 피하고 비동기 코드를 보다 가독성 높은 형태로 작성할 수 있습니다.

아래는 비동기 연산을 처리하는 제너레이터 함수의 예제입니다.

function* asyncFunction() {
  const result = yield fetch('https://api.example.com/data');
  console.log(result);
}

function run(generator) {
  const iterator = generator();

  function iterate(iteration) {
    if (iteration.done) {
      return Promise.resolve(iteration.value);
    }
    return Promise.resolve(iteration.value)
      .then(x => iterate(iterator.next(x)))
      .catch(x => iterator.throw(x));
  }

  try {
    return iterate(iterator.next());
  } catch (ex) {
    return Promise.reject(ex);
  }
}

run(asyncFunction);

위의 예제에서 asyncFunction 제너레이터 함수는 fetch 함수를 통해 비동기 데이터를 가져옵니다. yield 키워드를 통해 비동기 함수의 결과를 받고, 이후에 해당 결과를 처리하는 로직을 작성할 수 있습니다. run 함수는 제너레이터를 실행하고 비동기 연산을 처리하기 위한 보조 함수입니다.

마무리

자바스크립트 제너레이터 함수는 함수의 실행 흐름을 중단하고 이어서 실행할 수 있는 강력한 기능을 제공합니다. 이를 활용하여 간편한 이터러블 객체 생성 및 비동기 연산 처리를 할 수 있습니다. 제너레이터 함수를 활용하여 코드를 간결하고 가독성 좋게 작성할 수 있으니, 다음 프로젝트에서는 자바스크립트 제너레이터 함수에 대해 고려해보세요!

References: