GRAMMAR

Public Notification
  • account_tree
  • bug_report

제너레이터 함수(generator function)

지정된 이름에 대한 새로운 제너레이터 함수를 바인딩한다.

개요

제너레이터 함수(generator function)는 일반적인 함수와 달리 제너레이터 함수를 호출하는 호출자에서 실행에 대한 제어를 가능하게 하는 특수한 메커니즘을 갖는 함수이다. 즉 제너레이터 함수는 함수를 호출하는 쪽에서 함수 실행을 일시 중지하고 재개하는 반복적인 처리를 가능하게 한다. 함수가 일시 중지될 때 마다 호출한 곳으로 어떠한 생성 값을 반환할 수 있고 반대로 호출할 때 값을 전달할 수도 있다.

제너레이터 함수의 생성과 특성

제너레이터 함수는 리터털과 생성자 함수로 생성이 가능하다. 이것은 일반적인 함수와 동일하다. 차이점은 function 키워드 바로 다음에 *를 붙여서 제너레이터 함수임을 구분하는 것이다. 또한 제너레이터 함수는 GeneratorFunction 객체의 GeneratorFunction() 생성자 함수로도 생성한다. 그러나 일반적으로 리터럴을 선호하고 사용한다.

함수 내부적으로는 yield라는 독특한 키워드를 사용한다. yield는 다양한 단어적 의미를 가지고 있지만 여기서는 "산출한다"라는 의미를 가지고 있다. 제너레이터 함수 내부에 yield 문을 다음과 같이 삽입하면 외부의 호출에 따라 실행을 일시 멈추고 <value> 를 반환한다. <value>는 다양한 유형의 값을 가질 수 있다.

yield <value>

이러한 yield 문을 제너레이터 함수 내부에 필요에 따라 얼마든지 작성할 수 있다. 만약에 <value>를 생략한 경우에는 실행을 일시 중지하는 것은 동일하고 반환할 값이 없으므로 대신  undefined를 반환한다.

제너레이터 함수의 예
function* demo() {
  yield "a";
  yield "b";
  yield "c";
}

제너레이터 함수의 제어

제너레이터 함수는 먼저 호출을 해서 Generator 객체를 생성해야 한다. 그리고 Generator 객체의 프로토타입 메소드를 사용하여 함수를 제어한다.

가장 많이 사용하는 메소드는 next()이다. next() 메소드를 호출하면 제너레이터 함수의 yield 문 순서에 따라 yield 키워드를 만나면 일시 중지하고 생성된 값을 반환한다. 다시 next() 메소드를 호출하면 일시 중지된 위치에서부터 다음 yield를 만날 때까지 실행을 재개한다. next() 메소드에 대해서는 해당 섹션을 참조하기 바란다.

next() 메소드로 제너레이터 함수 제어
function* demo() {
  let r = 10 + 10;
  yield r;
  r += 100;
  yield r;
}

const gDemo = demo();
console.log(gDemo.next());
//-> 20
console.log(gDemo.next());
//-> 120

위 코드의 실제 동작은 다음 [제너레이터 함수의 반환]에서 확인하기 바란다.

제너레이터 함수의 반환

제너레이터 함수가 값을 반환하는 경우는 몇 가지가 있다. 역시 대표적인 것은 yield일 것이다. 다른 경우로는 return이 있다. reutrn 문은 마찬가지로 어떤 값을 반환하지만 전통적인 의미대로 실행을 끝낸다. 즉 더이상의 이후 yield 문은 의미가 없어진다. yieldreturn 키워드 말고 Generator 객체의 메소드(return(), throw())를 통해서도 반환되는 경우가 있다.

yield 또는 return 문이 반환하는 값은 각각의 키워드 다음에 나오는 값이라고 했다. 하지만 실제로는 앞서 이야기 한 값을 포함한 객체를 반환한다. yield 또는 return 문에 의해서 반환되는 객체의 구조는 다음과 같다.

{
  value: <value>,
  done: <true|false>
}

value 프로퍼티는 실제로 반환되는 값을 가지며 done 프로퍼티는 제네레이터 함수의 동작 상태를 나타낸다. done은 "끝났다"라는 의미로 제너레이터 함수가 더 이상의 next() 메소드의 호출을 받을 수 없는 경우 다시 말해 제너레이터 함수가 최종 종료된 경우에는 true로 설정된다. 제너레이터 함수 밖에서는 반환되는 done의 값을 통해서 제너레이터 함수의 종료 여부를 확인할 수 있을 것이다.

다음 라이브 코드에서 반환되는 값을 확인할 수 있다.

제너레이터 함수의 활용

제너레이터 함수는 독특한 작동 방식으로 인해 범용적으로 사용하는 함수 유형은 아니다. 한편으로 제너레이터 함수는 이터레이션 프로토콜(iteration protocol)을 준수하기 때문에 반복적인 처리가 필요한 경우에 꽤 유용할 수 있다. 지금까지는 netx() 메소드를 명시적으로 호출했지만 이터러블(iterable) 객체답게 반복문 처리를 할 수도 있다. 현재 문서에서는 제너레이터 함수의 기본을 다르므로 다음과 같은 간단한 샘플 코드를 소개로 제너레이터 함수의 소개를 마치고자 한다.