병행 처리란
여러 외부 API에의 요청이나 데이터베이스의 집계 처리 등, 서로 의존하지 않는 여러 처리를 순서대로 실행하면 합계 시간은 각각의 처리 시간의 합계가 됩니다. 이것들을 동시에 실행하면 합계 시간은 가장 시간이 걸리는 처리 1건분으로 단축할 수 있습니다. Laravel의Concurrency 파사드는 이러한 병행 실행을 단순한 API로 실현합니다.
Concurrency 파사드는 Laravel 11에서 도입되었으며, Laravel 13에서도 계속 이용할 수 있습니다.
기본 드라이버는 자식 PHP 프로세스를 사용하기 때문에 추가 패키지 없이 동작합니다.구조
Concurrency 파사드는 전달된 클로저를 직렬화하여 숨겨진 Artisan 명령어에 보내고, 각각 별도의 PHP 프로세스로서 실행합니다.
처리가 완료되면 반환값을 직렬화하여 부모 프로세스에 반환합니다.
3개의 드라이버가 준비되어 있습니다.
기본적인 사용법
Concurrency::run()
run() 메서드에 클로저의 배열을 전달하면, 그것들이 병행 실행됩니다.
반환값은 각 클로저가 반환한 값을 배열로 받습니다.
드라이버 지정
특정 드라이버를 사용하고 싶은 경우driver() 메서드로 지정합니다.
default 옵션을 업데이트합니다.
fork 드라이버의 사용법
fork 드라이버는 process 드라이버보다 고속이지만, PHP의 CLI 환경(Artisan 명령어나 큐 워커)에서만 사용할 수 있습니다.
Web 요청 중에는 사용할 수 없습니다.
사용 전에 spatie/fork 패키지를 설치하십시오.
실행 결과를 받지 않기: Concurrency::defer()
처리의 결과에는 관심이 없고, HTTP 응답을 반환한 후에 백그라운드에서 실행하고 싶은 경우는defer() 메서드를 사용합니다.
defer()를 호출한 시점에서는 클로저는 실행되지 않습니다.
HTTP 응답이 사용자에게 전송된 후에 병행하여 실행됩니다.
실전 예시: 여러 외부 API를 동시에 호출
EC 사이트의 대시보드에서 재고 관리 API, 매출 집계 API, 배송 상황 API의 3개에서 정보를 취득하는 예시를 생각합니다.순차 실행(개선 전)
병행 실행(개선 후)
여러 데이터베이스 집계를 동시 실행
테스트 시의 설정
테스트 환경에서는sync 드라이버를 사용하면 클로저를 순서대로 실행합니다.
병행 실행에 의한 프로세스의 기동 비용이 없어 테스트가 고속화됩니다.
.env.testing에서 기본 드라이버를 변경하는 방법도 있습니다.
주의 사항
클로저에 할 수 있는 제한
클로저에 할 수 있는 제한
클로저는 직렬화되어 자식 프로세스에 전달됩니다.
직렬화할 수 없는 객체(데이터베이스 접속, 파일 핸들, 리소스 등)를 클로저의 외측에서 캡처할 수는 없습니다.
필요한 객체는 클로저 안에서 새로 생성해 주십시오.
process 드라이버의 오버헤드
process 드라이버의 오버헤드
process 드라이버는 자식 프로세스의 기동 비용이 있기 때문에, 처리 자체가 매우 짧은(수 밀리초 이하) 경우는 병행 실행해도 빨라지지 않는 경우가 있습니다.
HTTP 요청이나 데이터베이스 집계 등, 처리에 100ms 이상 걸리는 것을 병행화할 때 효과를 발휘합니다.fork 드라이버의 제한
fork 드라이버의 제한
fork 드라이버는 PHP의 프로세스를 fork하기 때문에 Web 요청 중(FPM이나 Apache)에는 사용할 수 없습니다.
Artisan 명령어나 큐 워커 안에서만 사용해 주십시오.예외의 취급
예외의 취급
병행 실행 중에 예외가 발생하면
run()은 예외를 다시 던집니다.
개별 처리에서 예외가 발생해도 다른 처리를 계속시키고 싶은 경우, 클로저 안에서 try/catch를 사용해 주십시오.다음 단계
큐와 잡
처리를 백그라운드에서 비동기 실행하는 큐와 잡의 사용법을 배웁니다