Skip to content

동시성

소개

exclamation

Laravel의 Concurrency 파사드는 커뮤니티 피드백을 수집하는 동안 현재 베타 버전입니다.

때로는 서로 종속되지 않는 여러 느린 작업을 실행해야 할 수 있습니다. 많은 경우 작업을 동시에 실행하여 상당한 성능 향상을 실현할 수 있습니다. Laravel의 Concurrency 파사드는 클로저를 동시에 실행하기 위한 간단하고 편리한 API를 제공합니다.

동시성 호환성

Laravel 10.x 애플리케이션에서 Laravel 11.x로 업그레이드한 경우 애플리케이션의 config/app.php 구성 파일에 있는 providers 배열에 ConcurrencyServiceProvider를 추가해야 할 수 있습니다.

'providers' => ServiceProvider::defaultProviders()->merge([
/*
* Package Service Providers...
*/
Illuminate\Concurrency\ConcurrencyServiceProvider::class,
 
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
])->toArray(),

작동 방식

Laravel은 주어진 클로저를 직렬화하고 숨겨진 Artisan CLI 명령으로 디스패치하여 동시성을 달성합니다. 이 명령은 클로저를 역직렬화하고 자체 PHP 프로세스 내에서 호출합니다. 클로저가 호출된 후, 결과 값은 부모 프로세스로 다시 직렬화됩니다.

Concurrency 파사드는 세 가지 드라이버(process(기본값), fork, sync)를 지원합니다.

fork 드라이버는 기본 process 드라이버에 비해 향상된 성능을 제공하지만, PHP는 웹 요청 중에 포크를 지원하지 않으므로 PHP의 CLI 컨텍스트 내에서만 사용할 수 있습니다. fork 드라이버를 사용하기 전에 spatie/fork 패키지를 설치해야 합니다.

composer require spatie/fork

sync 드라이버는 모든 동시성을 비활성화하고 단순히 부모 프로세스 내에서 주어진 클로저를 순서대로 실행하려는 테스트 중에 주로 유용합니다.

동시 작업 실행하기

동시 작업을 실행하려면 Concurrency 파사드의 run 메서드를 호출하면 됩니다. run 메서드는 자식 PHP 프로세스에서 동시에 실행되어야 하는 클로저 배열을 허용합니다.

use Illuminate\Support\Facades\Concurrency;
use Illuminate\Support\Facades\DB;
 
[$userCount, $orderCount] = Concurrency::run([
fn () => DB::table('users')->count(),
fn () => DB::table('orders')->count(),
]);

특정 드라이버를 사용하려면 driver 메서드를 사용할 수 있습니다.

$results = Concurrency::driver('fork')->run(...);

또는 기본 동시성 드라이버를 변경하려면 config:publish Artisan 명령을 통해 concurrency 구성 파일을 게시하고 파일 내에서 default 옵션을 업데이트해야 합니다.

php artisan config:publish concurrency

동시 작업 연기

클로저 배열을 동시에 실행하고 싶지만 해당 클로저에서 반환되는 결과에는 관심이 없다면 defer 메서드를 사용하는 것을 고려해야 합니다. defer 메서드가 호출되면 주어진 클로저가 즉시 실행되지 않습니다. 대신, 라라벨은 HTTP 응답이 사용자에게 전송된 후 해당 클로저를 동시에 실행합니다.

use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;
 
Concurrency::defer([
fn () => Metrics::report('users'),
fn () => Metrics::report('orders'),
]);