제너레이터(Generators)란?
JavaScript는 제너레이터 함수(Generator Function)와 제너레이터 객체(Generator Object)를 지원합니다. 제너레이터 함수는 겉보기에는 일반 함수와 같지만, 값을 생성할 때 'return' 대신 'yield' 키워드를 사용한다는 점이 크게 다릅니다.
'yield' 키워드는 함수의 실행을 일시 중단하고 그 시점의 값을 호출자(caller)에게 전달합니다. 그리고 나중에 중단되었던 바로 그 위치부터 실행을 재개할 수 있는 것이 제너레이터의 가장 큰 특징입니다. 즉, 한 번의 호출로 끝나는 일반 함수와 달리, 제너레이터는 여러 번에 걸쳐 값을 순차적으로 생산해 내는 지연 평가(lazy evaluation) 방식으로 동작합니다.
문법(Syntax)
function* generator() {
yield 1;
yield 2;
}
함수 키워드 뒤에 별표(*)를 붙이면 해당 함수가 제너레이터 함수로 선언됩니다. 제너레이터 함수를 호출하면 코드가 즉시 실행되지 않고 제너레이터 객체가 반환되며, 이 객체의 next() 메서드를 호출할 때마다 다음 yield 표현식까지 코드가 실행됩니다.
예제(Example)
아래 예제에서는 제너레이터 함수를 사용하여 자연수 10, 9, 8을 차례대로 출력합니다. 각 숫자를 일일이 출력하는 대신 반복문(for 루프)과 함께 활용하면, 원하는 만큼의 숫자를 유연하게 생성해 낼 수 있습니다.
<html>
<body>
<script>
function * number() {
var num = 10;
while (true) {
yield num--;
}
}
var gen = number();
document.write(gen.next().value);
document.write("</br>");
document.write(gen.next().value);
document.write("</br>");
document.write(gen.next().value);
</script>
</body>
</html>
실행 결과(Output)
10 9 8
동작 방식 상세 설명
위 코드의 number() 함수는 while(true) 무한 루프를 포함하고 있지만 실제로 프로그램이 멈추지는 않습니다. yield num--에서 값 10을 반환한 순간 실행이 일시 중단되고, gen.next()가 다시 호출될 때마다 중단된 지점부터 실행을 이어가며 9, 8을 순차적으로 반환하기 때문입니다.
next() 메서드는 항상 { value: 값, done: true/false } 형태의 객체를 반환합니다. value는 yield로 전달된 값을 의미하고, done은 제너레이터의 실행이 모두 종료되었는지 여부를 나타냅니다. 이러한 특성 덕분에 제너레이터는 무한 시퀀스 처리, 데이터 스트림 생성, 비동기 흐름 제어 등 다양한 상황에서 유용하게 활용될 수 있습니다.