동시성
번역일: 2026년 6월 20일
동시성
소개
WARNING
Laravel의 Concurrency 파사드는 현재 커뮤니티 피드백을 수집하는 베타 단계입니다.
서로 의존하지 않는 여러 개의 느린 작업을 실행해야 할 때가 있습니다. 이런 경우 작업들을 동시에 실행하면 성능을 크게 향상시킬 수 있습니다. Laravel의 Concurrency 파사드는 클로저를 동시에 실행하기 위한 간단하고 편리한 API를 제공합니다.
호환성 참고사항
Laravel 10.x에서 11.x로 업그레이드한 경우, config/app.php의 providers 배열에 ConcurrencyServiceProvider를 직접 추가해야 할 수 있습니다:
'providers' => ServiceProvider::defaultProviders()->merge([ /* * 패키지 서비스 프로바이더... */ Illuminate\Concurrency\ConcurrencyServiceProvider::class, // /* * 애플리케이션 서비스 프로바이더... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class,])->toArray(),동작 원리
Laravel은 전달받은 클로저를 직렬화(serialize)한 뒤, 숨겨진 Artisan CLI 명령으로 디스패치하는 방식으로 동시성을 구현합니다. 해당 명령은 별도의 PHP 프로세스에서 클로저를 역직렬화하여 실행하고, 결과값을 다시 직렬화해 부모 프로세스로 반환합니다.
Concurrency 파사드는 세 가지 드라이버를 지원합니다: process(기본값), fork, sync.
fork 드라이버는 기본 process 드라이버보다 성능이 뛰어나지만, PHP는 웹 요청 중 포킹을 지원하지 않으므로 CLI 환경에서만 사용할 수 있습니다. fork 드라이버를 사용하려면 먼저 spatie/fork 패키지를 설치해야 합니다:
composer require spatie/forksync 드라이버는 주로 테스트 환경에서 유용합니다. 모든 동시성을 비활성화하고 클로저를 부모 프로세스에서 순차적으로 실행하므로, 동시 실행 없이 로직만 검증하고 싶을 때 적합합니다.
동시 작업 실행
동시 작업을 실행하려면 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(),
]);NOTE
반환값은 전달한 클로저 배열의 순서와 동일한 순서로 배열에 담겨 반환됩니다. 배열 구조 분해를 활용하면 위 예시처럼 깔끔하게 결과를 받을 수 있습니다.
특정 드라이버를 사용하려면 driver 메서드를 체이닝하면 됩니다:
$results = Concurrency::driver('fork')->run(...);기본 동시성 드라이버를 변경하려면 config:publish Artisan 명령으로 concurrency 설정 파일을 퍼블리시한 뒤, 파일 내 default 옵션을 수정하세요:
php artisan config:publish concurrency동시 작업 지연 실행
클로저 배열을 동시에 실행하되, 그 반환값에는 관심이 없는 경우 defer 메서드를 사용하는 것을 권장합니다. defer를 호출해도 클로저는 즉시 실행되지 않습니다. 대신 Laravel은 HTTP 응답이 사용자에게 전송된 이후에 클로저들을 동시에 실행합니다:
use App\Services\Metrics;
use Illuminate\Support\Facades\Concurrency;
Concurrency::defer([
fn () => Metrics::report('users'),
fn () => Metrics::report('orders'),
]);NOTE
defer는 사용자 응답 시간에 영향을 주지 않고 백그라운드 처리를 수행하고 싶을 때 유용합니다. 예를 들어 지표(metrics) 기록, 로그 전송, 외부 API 알림 등 응답 결과에 영향을 주지 않는 부수 작업에 적합합니다.