PHP Academy · 강의

PHP 8.1 파이버

네이티브 파이버로 실행을 일시 중지하고 재개합니다.

레슨 2/413개 단계

PHP 8.1 파이버은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

파이버가 제공하는 것

PHP 8.1에는 파이버가 추가되었습니다. 파이버는 실행 중인 호출 스택을 일시 중지했다가 완전히 다른 위치에서 나중에 재개할 수 있게 하는 핵심 기본 요소입니다. 파이버는 완전하고 독립적인 스택이므로 임의의 지점에서 일시 중지한 뒤 스택을 되감지 않고 계속 실행할 수 있습니다. 이 기능이 빠져 있었기 때문에 라이브러리는 프로미스 체인을 동기 코드처럼 보이는 await로 대체할 수 있게 되었습니다. 이는 ReactPHP와 앰프의 최신 API를 가능하게 하는 핵심 요소입니다.

첫 파이버

콜백으로 파이버를 만들고 start()한 다음, 파이버 스스로 suspend()하도록 하십시오. 일시 중지 지점에서 제어권이 호출자에게 돌아오며, resume()하면 정확히 그 지점부터 계속 실행됩니다.

<?php
$fiber = new Fiber(function (): void {
    echo "A: inside fiber\n";
    $received = Fiber::suspend('paused');
    echo "C: resumed with '$received'\n";
});

$value = $fiber->start();          // prints A, returns 'paused'
echo "B: fiber suspended, got '$value'\n";
$fiber->resume('hello');           // prints C
echo "D: fiber done\n";

네 가지 핵심 메서드

API는 작습니다.

  • $fiber->start(...$args) — 실행을 시작하고 첫 번째 일시 중지 값을 반환합니다.
  • Fiber::suspend($value) — 현재 파이버를 일시 중지하고 $value를 재개하는 쪽에 전달합니다.
  • $fiber->resume($value) — 실행을 계속하며 $value가 suspend()의 반환값이 됩니다.
  • $fiber->getReturn() — 파이버가 종료된 후 콜백이 반환한 값을 가져옵니다.

일시 중지 경계를 넘어 값이 양방향으로 이동합니다.

양방향 값 전달

파이버는 요청을 밖으로 양보하고 응답을 다시 받을 수 있습니다. 이는 이벤트 루프가 일시 중지된 작업에 입출력 결과를 전달하는 방식의 핵심입니다.

<?php
$fiber = new Fiber(function (): int {
    $a = Fiber::suspend('need first number');
    $b = Fiber::suspend('need second number');
    return $a + $b;
});

$fiber->start();        // suspends: 'need first number'
$fiber->resume(10);     // a = 10, suspends: 'need second number'
$fiber->resume(32);     // b = 32, fiber returns
echo $fiber->getReturn(), PHP_EOL; // 42

파이버 상태와 검사

파이버의 수명 주기를 확인할 수 있습니다. 종료된 파이버에서 resume()을 호출하면 FiberError가 발생하므로, 스케줄러를 만들 때는 이러한 확인으로 호출을 보호하십시오.

<?php
$fiber = new Fiber(function () { Fiber::suspend(); });
var_dump($fiber->isStarted());     // false
$fiber->start();
var_dump($fiber->isStarted());     // true
var_dump($fiber->isSuspended());   // true
var_dump($fiber->isRunning());     // false (we're outside it)
$fiber->resume();
var_dump($fiber->isTerminated());  // true

작은 스케줄러 만들기

파이버와 큐를 결합하면 협력형 스케줄러가 됩니다. 각 작업은 제어권을 양보하기 위해 일시 중지하고, 스케줄러는 모든 작업이 끝날 때까지 순환 방식으로 실행합니다. 이것이 모든 비동기 런타임 내부에 있는 기본 뼈대입니다.

<?php
$tasks = [];
foreach (['X', 'Y', 'Z'] as $name) {
    $tasks[] = new Fiber(function () use ($name) {
        for ($i = 1; $i <= 2; $i++) {
            echo "$name step $i\n";
            Fiber::suspend();   // give others a turn
        }
    });
}
foreach ($tasks as $t) { $t->start(); }
while ($tasks) {
    foreach ($tasks as $k => $t) {
        if ($t->isTerminated()) { unset($tasks[$k]); continue; }
        $t->resume();
    }
}

경계를 넘는 예외

throwInto()는 일시 중지 지점에 예외를 주입합니다($fiber->throw() 형태의 API에서는 throw()라고 부릅니다). 이는 루프가 실패한 입출력 작업을 대기 중인 작업에 알리는 방식입니다. 예외는 파이버가 일시 중지된 정확한 위치에서 나타납니다.

<?php
$fiber = new Fiber(function () {
    try {
        Fiber::suspend();
    } catch (RuntimeException $e) {
        echo 'caught: ' . $e->getMessage() . PHP_EOL;
    }
});
$fiber->start();
$fiber->throw(new RuntimeException('io failed')); // prints: caught: io failed

파이버와 제너레이터 비교

제너레이터(yield)도 일시 중지할 수 있지만, 최상위 함수만 일시 중지합니다. 제너레이터를 사용해 중첩된 도우미 함수에서 대기하려면 스택의 최상위까지 yield from을 계속 전달해야 하므로 모든 함수가 제너레이터 방식으로 바뀝니다. 파이버는 전체 스택을 일시 중지하므로 어느 깊이에서든 호출자를 알리지 않고 Fiber::suspend()할 수 있습니다. 따라서 await가 yield가 아닌 일반 함수 호출이 될 수 있습니다.

<?php
function deep(): string {
    // No yield needed in the call chain — suspends the whole fiber
    return Fiber::suspend('awaiting from deep');
}
$f = new Fiber(fn() => print(deep() . PHP_EOL));
$f->start();
$f->resume('value injected at depth');

일시 중지 제한

단 하나의 엄격한 규칙이 있습니다. Fiber::suspend()는 파이버 내부에서만 호출할 수 있습니다. 주 스레드에서 일시 중지하거나 파이버를 지원하지 않는 C 수준 콜백(일부 레거시 usort 비교 함수와 특정 내부 콜백)에서 일시 중지하면 FiberError: Cannot suspend outside of a fiber가 발생합니다. 라이브러리는 모든 사용자 코드가 루프가 구동하는 파이버 내부에서 실행되도록 보장하여 이 제한을 감춥니다.

<?php
try {
    Fiber::suspend(); // main thread — illegal
} catch (FiberError $e) {
    echo $e->getMessage(), PHP_EOL; // Cannot suspend outside of a fiber
}

라이브러리가 파이버를 사용하는 방법

애플리케이션 코드에서 원시 파이버를 직접 작성하는 경우는 드뭅니다. 앰프 v3나 ReactPHP(파이버를 통해)와 같은 프레임워크가 파이버를 감쌉니다. await($promise)는 내부적으로 Fiber::suspend()를 호출하고 이벤트 루프에 후속 작업을 등록한 다음, 입출력이 완료되면 resume()하여 파이버를 재개합니다. 코드는 동기식으로 보이고, 런타임이 일시 중단과 스케줄링을 처리합니다.

<?php
// Conceptual: what an await() helper does under the hood
function await(Promise $p): mixed {
    $fiber = Fiber::getCurrent() ?? throw new Error('await() outside fiber');
    $p->then(fn($v) => $fiber->resume($v),
             fn($e) => $fiber->throw($e));
    return Fiber::suspend(); // parked until the promise settles
}

메모리와 수명 주기 주의사항

각 파이버는 자체 스택을 할당하므로 수십만 개를 생성하면 메모리 비용이 발생합니다(OS 스레드보다는 훨씬 가볍습니다). 무언가가 계속 참조하는 한 영원히 일시 중지된 파이버는 가비지 컬렉션 대상이 되지 않습니다. 이는 오래 실행되는 서버에서 발생할 수 있는 미묘한 누수입니다. 또한 파이버의 콜백에서 처리되지 않은 예외가 발생하면 resume()/start() 호출 밖으로 전파되므로, 스케줄러는 재개 작업을 try/catch로 감싸야 합니다.

<?php
$fiber = new Fiber(function () {
    throw new RuntimeException('boom inside fiber');
});
try {
    $fiber->start(); // exception surfaces here, at the resumer
} catch (RuntimeException $e) {
    echo 'scheduler caught: ' . $e->getMessage() . PHP_EOL;
}

간단한 확인

비동기 처리에서 제너레이터보다 파이버가 갖는 핵심 장점은 무엇입니까?

요약

파이버는 PHP의 저수준 동시성 기본 요소입니다.

  • start(), Fiber::suspend(), resume(), getReturn()은 전체 호출 스택을 일시 중지하고 계속 실행하며, 값을 양방향으로 전달합니다.
  • 상태 메서드(isSuspended, isTerminated)와 throw()를 사용하면 협력형 스케줄러를 만들고 입출력 오류를 주입할 수 있습니다.
  • 제너레이터와 달리 파이버는 어느 깊이에서든 일시 중지할 수 있으므로 투명한 await()를 구현할 수 있습니다.
  • 파이버는 내부에서만 일시 중지할 수 있습니다. 앰프와 ReactPHP 같은 프레임워크는 파이버를 감싸 비동기 코드가 동기식으로 읽히게 합니다.
무료로 시작

AI 튜터와 함께 PHP을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
49
레슨
195

자주 묻는 질문

“PHP 8.1 파이버” 강의는 무료인가요?

네 — “PHP 8.1 파이버” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“PHP 8.1 파이버”에서 뭘 배우나요?

네이티브 파이버로 실행을 일시 중지하고 재개합니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

PHP Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“PHP 8.1 파이버” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. PHP 동시성 모델
  2. PHP 8.1 파이버
  3. ReactPHP의 이벤트 루프
  4. Swoole을 활용한 고성능 서버
← PHP Academy(으)로 돌아가기