여러 외부 API에의 요청이나 데이터베이스의 집계 처리 등, 서로 의존하지 않는 여러 처리를 순서대로 실행하면 합계 시간은 각각의 처리 시간의 합계가 됩니다.
이것들을 동시에 실행하면 합계 시간은 가장 시간이 걸리는 처리 1건분으로 단축할 수 있습니다.Laravel의 Concurrency 파사드는 이러한 병행 실행을 단순한 API로 실현합니다.
Concurrency 파사드는 Laravel 11에서 도입되었으며, Laravel 13에서도 계속 이용할 수 있습니다.
기본 드라이버는 자식 PHP 프로세스를 사용하기 때문에 추가 패키지 없이 동작합니다.
use Illuminate\Support\Facades\Http;public function dashboard(): array{ // 각 요청이 순서대로 완료할 때까지 대기(합계 약 3초) $inventory = Http::get('https://api.example.com/inventory')->json(); $sales = Http::get('https://api.example.com/sales')->json(); $shipping = Http::get('https://api.example.com/shipping')->json(); return compact('inventory', 'sales', 'shipping');}
클로저는 직렬화되어 자식 프로세스에 전달됩니다.
직렬화할 수 없는 객체(데이터베이스 접속, 파일 핸들, 리소스 등)를 클로저의 외측에서 캡처할 수는 없습니다.
필요한 객체는 클로저 안에서 새로 생성해 주십시오.
// NG: 외측의 Eloquent 모델을 캡처$user = User::find(1);Concurrency::run([ fn () => $user->orders()->count(), // 직렬화할 수 없을 가능성이 있음]);// OK: 클로저 안에서 데이터를 취득$userId = 1;Concurrency::run([ fn () => Order::where('user_id', $userId)->count(),]);
process 드라이버의 오버헤드
process 드라이버는 자식 프로세스의 기동 비용이 있기 때문에, 처리 자체가 매우 짧은(수 밀리초 이하) 경우는 병행 실행해도 빨라지지 않는 경우가 있습니다.
HTTP 요청이나 데이터베이스 집계 등, 처리에 100ms 이상 걸리는 것을 병행화할 때 효과를 발휘합니다.
fork 드라이버의 제한
fork 드라이버는 PHP의 프로세스를 fork하기 때문에 Web 요청 중(FPM이나 Apache)에는 사용할 수 없습니다.
Artisan 명령어나 큐 워커 안에서만 사용해 주십시오.
예외의 취급
병행 실행 중에 예외가 발생하면 run()은 예외를 다시 던집니다.
개별 처리에서 예외가 발생해도 다른 처리를 계속시키고 싶은 경우, 클로저 안에서 try/catch를 사용해 주십시오.
Concurrency::run([ function () { try { return Http::get('https://api.example.com/data')->json(); } catch (\Exception $e) { return null; // 실패 시는 null 을 반환 } },]);