Skip to main content

이 페이지에 대해

패키지 개발 기초에서는 composer.jsonextra.laravel 섹션을 작성하면 서비스 프로바이더와 파사드가 자동 등록된다는 점을 소개했습니다. 이 페이지에서는 그 이면, 즉 Illuminate\Foundation\PackageManifest 클래스가 어떻게 동작하는지를 소스코드 수준에서 설명합니다.
이 페이지는 패키지 개발 기초의 자매 페이지입니다. 자동 감지의 기본적인 사용법을 먼저 읽어 보시길 권장합니다.

자동 감지의 전체 흐름

PackageManifest 클래스

자동 감지의 중심은 Illuminate\Foundation\PackageManifest입니다. 다음은 프레임워크 13.x 기준의 구현(요약)입니다.
핵심 포인트는 다음 세 가지입니다.
  • 매니페스트는 한 번 로드되면 메모리에 캐시된다 ($this->manifest 프로퍼티). 한 요청 내에서 providers()를 여러 번 호출해도 파일 I/O는 한 번만 발생합니다.
  • 매니페스트 파일이 존재하지 않는 경우에만 build()가 실행된다. 일반 운영 시에는 매번 빌드되지 않습니다.
  • 실체는 소박한 PHP 배열을 return하는 파일(bootstrap/cache/packages.php)로, require만으로 로드할 수 있는 가장 빠른 형식입니다.

매니페스트 빌드 처리

build() 메서드가 실제로 composer.json 정보를 집약하는 부분입니다.
중요한 점은 composer.json을 직접 파싱하는 것이 아니라 vendor/composer/installed.json 을 읽는다는 것입니다. 이는 Composer가 composer install / composer update 실행 시 생성하는, 설치된 모든 패키지의 메타데이터 파일입니다. 각 패키지의 composer.json에 작성된 extra 섹션이 여기에 집약되므로 Laravel 쪽은 Composer 관리하의 정보만 신뢰하여 읽습니다.
installed.json은 일반적으로 .gitignore되므로, 초기 설정 시(vendor/가 없는 상태)에는 자동 감지가 작동하지 않습니다. composer install이 완료된 후에야 캐시가 구축됩니다.

dont-discover의 두 가지 작성 방식

dont-discover는 패키지 측과 애플리케이션 측 어느 composer.json에도 작성할 수 있지만, 의미가 다릅니다.
패키지 측 composer.json
애플리케이션 측 composer.json
build()의 구현을 보면 $ignore 배열은 각 패키지의 configuration['dont-discover']array_merge하여 축적하고 있습니다. 즉 패키지 자신이 “자신의 의존 패키지의 자동 감지를 비활성화”하는 것도 기술적으로는 가능합니다(예: 내부에서 사용하는 서브 패키지의 프로바이더를 중복 등록시키고 싶지 않은 경우). 다만 실무에서 자주 사용되는 것은 애플리케이션 측에서의 비활성화입니다.

dont-discover* 지정하기

packagesToIgnore()가 반환하는 배열에 *가 포함되면 $ignoreAll = true가 되어 모든 패키지의 자동 감지가 통째로 비활성화됩니다. CI나 테스트 환경에서 자동 감지의 오버헤드를 피하고 싶은 경우나 bootstrap/providers.php에서 완전히 수동 관리하고 싶은 경우에 사용합니다.

캐시 파일의 실체

getCachedPackagesPath()는 환경 변수 APP_PACKAGES_CACHE가 있으면 그것을, 없으면 bootstrap/cache/packages.php를 반환합니다.
이 파일을 직접 열어보면, 단순한 연관 배열을 return하고 있음을 알 수 있습니다.
패키지명이 키가 되므로, php artisan package:discover의 출력에서 “어떤 패키지가 감지되었는지” 확인할 수 있습니다.

캐시가 재구축되는 시점

Illuminate\Foundation\ComposerScripts는 3개의 Composer 이벤트에 훅을 걸고 있으며, 모두 같은 clearCompiled()를 호출합니다.
composer install / composer update / composer dump-autoload 중 어느 것을 실행해도 설정 캐시·서비스 캐시·패키지 캐시가 모두 삭제됩니다. 다음에 Laravel이 시작되는 시점에 PackageManifest::build()가 실행되어 installed.json의 최신 상태에서 재구축됩니다. 이는 composer.jsonscripts에 등록된, 표준적인 Laravel 프로젝트의 동작입니다.
Laravel 앱의 composer.json (발췌)

php artisan package:discover로 수동 재구축

캐시가 오래된 상태로 남아 있거나, Composer를 거치지 않고 vendor/를 직접 변경한 경우에는 package:discover 명령으로 수동 재구축할 수 있습니다.
이 명령의 실체는 매우 얇은 래퍼입니다.
$manifest->build()를 호출하여 결과를 출력할 뿐이며, 명령 고유의 로직은 거의 없습니다. CI 파이프라인에서 composer install --no-scripts를 사용하는 등, Composer 이벤트가 발생하지 않는 상황에서는 이 명령을 명시적으로 호출할 필요가 있습니다.
패키지 테스트에서 Orchestra Testbench를 사용하는 경우, Testbench는 독자적인 vendor/bin/testbench package:discover 명령을 제공합니다. 자세한 내용은 Testbench에서 패키지 테스트를 참조하세요. Artisan의 package:discover와는 별개로, Testbench 전용 스켈레톤 앱을 위해 매니페스트를 구축합니다.

배포 시 주의점

프로덕션 배포에서는 composer install --no-dev --optimize-autoloader를 실행하는 것이 일반적이지만, --no-scripts를 지정한 경우에는 패키지 캐시가 업데이트되지 않습니다. 배포 스크립트에 명시적인 재구축 단계를 넣어두면 안전합니다.
순서도 중요합니다. package:discoverconfig:cache보다 먼저 실행하세요. 설정 캐시가 먼저 만들어지면 나중에 추가된 패키지 설정(mergeConfigFrom으로 등록되는 설정 등)이 반영되지 않을 수 있습니다.

정리

  • 자동 감지는 composer.json의 정적 내용이 아니라, Composer가 생성한 vendor/composer/installed.json을 읽어 동작한다.
  • 결과는 bootstrap/cache/packages.php에 순수한 PHP 배열로 캐시되며, require만으로 빠르게 로드된다.
  • 캐시는 composer install/update/dump-autoload의 각 이벤트에서 자동으로 삭제되고, 다음 시작 시 재구축된다.
  • --no-scripts로 Composer를 실행하는 환경에서는 php artisan package:discover를 명시적으로 호출할 필요가 있다.
  • dont-discover*를 지정하면 자동 감지 전체를 비활성화할 수 있다.

관련 페이지

마지막 수정일 2026년 8월 2일