Computer >> 컴퓨터 >  >> 프로그래밍 >> PHP

PHP 제너레이터(Generator) 완벽 가이드: yield 키워드로 메모리 효율적인 반복 처리하기

PHP 제너레이터란 무엇인가?

대량의 데이터를 foreach 같은 반복 구조로 순회하려면 많은 메모리와 상당한 처리 시간이 필요합니다. 하지만 제너레이터(generator)를 사용하면 이러한 오버헤드 없이도 데이터 집합을 손쉽게 순회할 수 있습니다.

제너레이터 함수는 겉보기에 일반 함수와 매우 비슷합니다. 다만 일반 함수가 return 문으로 값을 반환하고 종료되는 것과 달리, 제너레이터는 yield 키워드를 사용하여 값을 하나씩 반복적으로 제공합니다.

yield 키워드는 제너레이터 메커니즘의 핵심입니다. return 문과 사용법이 비슷해 보이지만, yield는 함수의 실행을 완전히 중단하지 않습니다. 대신 다음 순회에 사용할 값을 제공한 뒤 함수 실행을 일시 중지(pause)하고, 다음 값이 요청될 때마다 중지된 지점부터 실행을 재개합니다.

yield로 값 생성하기

제너레이터 함수 내부에서 for 반복문을 사용하면, 반복 변수의 각 값을 순차적으로 yield할 수 있습니다. 아래 예제들을 통해 실제 동작 방식을 살펴보겠습니다.

예제 1: 제곱 값 생성하기

<?php
function squaregenerator(){
    for ($i=1; $i<=5; $i++){
        yield $i*$i;
    }
}
$gen=squaregenerator();
foreach ($gen as $val){
    echo $val . " ";
}
?>

foreach 문이 처음으로 $val을 출력하려고 할 때, squaregenerator는 첫 번째 값을 yield한 후 $i의 상태를 그대로 유지한 채 실행을 멈춥니다. 그리고 foreach가 다음 반복을 진행하면 중지된 지점부터 다시 실행됩니다. 출력 결과는 일반 foreach 반복문과 동일하게 나타납니다.

실행 결과

1 4 9 16 25

예제 2: range() 함수를 제너레이터로 구현하기

PHP의 내장 함수인 range()는 $start부터 $stop까지 $step 간격으로 정수 목록을 반환합니다. 다음 프로그램은 range() 함수와 동일한 기능을 제너레이터로 구현한 것입니다.

<?php
function rangegenerator($start, $stop, $step){
    for ($i=$start; $i<=$stop; $i+=$step){
        yield $i;
    }
}
foreach (rangegenerator(2,10,2) as $val){
    echo $val . " ";
}
?>

실행 결과

출력 결과는 range(2,10,2)를 호출한 것과 동일합니다.

2 4 6 8 10

예제 3: 연관 배열을 제너레이터로 순회하기

연관 배열(associative array) 역시 제너레이터로 처리할 수 있습니다. 키(key)와 값(value)을 함께 yield하면 됩니다.

<?php
function arrgenerator($arr){
    foreach ($arr as $key=>$val){
        yield $key=>$val;
    }
}
$arr=array("one"=>1, "two"=>2, "three"=>3, "four"=>4);
$gen=arrgenerator($arr);
foreach ($gen as $key=>$val)
echo $key . "=>" . $val . "\n";
?>

실행 결과

one=>1
two=>2
three=>3
four=>4

정리

제너레이터는 전체 데이터를 메모리에 한꺼번에 올리지 않고 필요할 때마다 값을 하나씩 생성하기 때문에, 대용량 데이터나 무한 시퀀스를 다룰 때 특히 유용합니다. yield 키워드의 동작 원리만 이해하면 기존 반복문 로직을 손쉽게 제너레이터로 변환하여 메모리 사용량과 처리 시간을 크게 절약할 수 있습니다.