ES2015 사양에는 Node.js 어플리케이션의 비동기 제어 흐름을 단순화 하는데 사용할 수 있는 또 다른 매커니즘이 있는데 세미 코루틴이라고 하는 제너레이터가 그것이다. 이것은 다른 진입점이 있을 수 있는 서브 루트들을 일반화한 것이다. 보통 함수에서는 실제 함수 자체의 호출에 해당하는 하나의 진입점만을 가질 수 있지만, 제너레이터는 함수와 비슷하나 Yield 문을 사용하여 일시적으로 실행의 흐름을 중지시켰다가 이후 다시 시작할 수 있다. 제너레이터는 반복자를 구현할 때 특히 유용한데 반복자 라는 것은 순차 및 제한된 병렬 실행과 같이 중요한 비동기 제어 흐름 패턴을 구현할때 유용하다.

제너레이터의 기본


비동기식 제어 흐름에 제너레이터를 적용해보기 전 그 개념부터 짚고 넘어간다. 제너레이터 함수는 function 키워드 다음에 * 연산자를 추가하여 선언한다.

function* newFunction() {}

이 함수 내에서 yield 키워드를 사용하여 실행을 일시 중지하고 전달된 값을 호출자에게 반환할 수 있다.

function* newFunction() {
	yield 'Hello world';
	console.log('re-start')
}

제너레이터 함수는 Hello World라는 문자열을 반환하는 곳에서 yield하여 멈추게 한다. 제너레이터가 next로 다시 시작하게 되면 console.log가 그제서야 실행이 된다. next()는 제너레이터 실행을 시작/재시작하는데 사용되며, 다음과 같은 형식의 객체를 반환한다.

{
	value: <yield시 반환값>,
	done: <제너레이터가 끝난는지의 대한 여부>
}

이 객체에는 제너레이터에서 생성한 값과 제너레이터의 실행이 완료되었는지 나타내는 플래그가 포함되어 있다.

간단한 예


function* newFunction() {
	yield 'apple';
	yield 'orange';
	return 'melon'
}

const generator = newFunction();
console.log(generator.next()) // { value: 'apple', done: false }
console.log(generator.next()) // { value: 'orange', done: false }
console.log(generator.next()) // { value: 'melon', done: true}

아래는 위 함수의 실행 동작에 대한 간단한 설명이다.