오토로더(Auto loader)
PHP 에 오토로딩 기능이 포함되었지만 app 개발자는 오토로딩할 클래스를 직접 spl_autoload_register 를 사용하여 일일이 등록해야 하는 번거로움이 있습니다.
컴포저는 사용할 패키지나 클래스가 있을 경우 간단하게 패키지명만 기술하면 자동으로 로딩해 주는 아주 편리하고 훌륭한 기능을 제공하고 있습니다.
이 책에서는 자동으로 클래스나 인터페이스를 로딩해 주는 것을 오토로딩으로 부르며 오토로딩을 수행하는 로더(Loader)를 오토로더(Auto Loader) 라고 호칭합니다.
만약 컴포저를 사용할 수 없는 오래된 프레임워크에서 외부 라이브러리를 사용하고 할 경우 매우 불편하고 귀찮은 작업을 수행해야 합니다.
파일 시스템을 추상화하여 로컬 파일이든 드랍박스에 저장된 파일이든 혹은 아마존 클라우드에 저장된 파일이든 단일한 인터페이스로 손쉽게 다룰 수 있는 유명한 라이브러리인 league/flysystem 패키지(라라벨 5에는 기본 탑재되어 있습니다.)를 프로젝트에서 사용한다고 가정해 봅시다.
만약 컴포저를 사용할수 없는 환경이라면 이 패키지를 사용하기 위해서는 다음과 같이 spl_autoload_register 함수에 패키지를 등록해야 사용할 수 있습니다.
spl_autoload_register(function($class) {
$prefix = 'League\\Flysystem\\';
if ( ! substr($class, 0, 17) === $prefix) {
return;
}
$class = substr($class, strlen($prefix));
$location = __DIR__ . 'path/to/flysystem/src/' . str_replace('\\', '/', $class) . '.php';
if (is_file($location)) {
require_once($location);
}
});
하지만 컴포저를 사용한다면 composer require league/flysystem 명령을 콘솔에서 실행하거나 다음과 같이 composer.json 의 require 항목에 의존성을 기술하고 composer update 를 실행하면 오토로더가 생성됩니다.
"require": {
"monolog/monolog": "^1.13",
"nesbot/carbon": "^1.19",
"league/flysystem": "^1.0"
},
오토로더는 classmap 과 psr-4 두 가지 방식을 사용할 수 있습니다. 다음은 composer.json 에 현재 프로젝트내 database 폴더는 classmap 방식의 오토로더를 사용하고 app 폴더는 App 라는 네임스페이스를 쓰는 psr-4 방식의 오토로더를 사용하겠다는 의미로 라라벨 5의 기본 설정입니다.
이제 클래스맵과 psr-4 방식의 차이점에 대해서 알아보도록 하겠습니다.
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
},
클래스맵 방식의 오토로더로 설정할 경우 클래스맵에 지정된 폴더내에 모든 php 를 읽어서 다음과 같은 정적 배열을 생성하고 이 파일들을 오토 로딩합니다.
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'App\\Commands\\Command' => $baseDir . '/app/Commands/Command.php',
'App\\Commands\\SeedMakeCommand' => $baseDir . '/app/Commands/SeedMakeCommand.php',
'App\\Console\\Commands\\Inspire' => $baseDir . '/app/Console/Commands/Inspire.php',
'App\\Console\\Kernel' => $baseDir . '/app/Console/Kernel.php',
정보를 정적으로 생성후 로딩하므로 클래스맵은 런타임에 처리 속도가 psr-4 보다 빠르지만 새로운 파일이나 폴더가 추가되면 컴포저에게 오토로딩 정보를 갱신해야 한다고 알려줘야 합니다. 이 명령어는 dump-autoload 또는 dumpautoload 명령어이며 vendor/autoload.php 에 새로운 클래스맵 오토로더를 생성합니다.
$ composer dump-autoload
psr-4 방식의 오토로더는 다음과 같이 네임스페이스와 이를 매칭시킬 디렉토리만 지정하게 되며 동적으로 런타임에 요청한 클래스나 인터페이스, 트레이트를 찾게 됩니다.
<?php
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
유명한 로그 라이브러리인 Monolog 패키지는 Monolog 네임스페이스가 vendor/monolog/monolog/src/Monolog 에 매핑되어 있습니다.
다음과 같이 Monolog 의 Logger 와 Handler\StreamHandler 클래스를 사용하는 소스가 있습니다.
<?php
include "vendor/autoload.php";
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('loggerName');
psr-4 방식의 오토로더는 vendor/monolog/monolog/src/Monolog 폴더내에서 네임스페이스를 기준으로 다음 경로에서 use 로 지정된 php 파일을 찾게 됩니다.
- vendor/monolog/monolog/src/Monolog/Logger.php
- vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
이렇게 psr-4는 use 지정된 클래스나 인터페이스에 따라 런타임에 동적으로 로딩하므로 클래스나 인터페이스가 추가되어도 새로 컴포저에게 알려주지 않아도 되므로 매우 유용하지만 클래스맵보다 속도가 느린 단점이 있습니다.
그러므로 개발 환경에서는 psr-4 를 사용하고 운영 환경은 클래스맵을 사용하는 것이 개발의 편의성 및 운영시 속도를 향상 시킬 수 있는 좋은 방법이며 컴포저는 이를 위해서 dump-autoload 명령어에 -o 옵션을 제공하고 있습니다.
운영 환경에서 다음 명령어를 실행할 경우 psr-0, psr-4 방식의 오토 로더를 클래스맵으로 덤프해 주므로 런타임에 클래스를 파일 시스템에서 찾지 않으므로 더욱 빠른 웹 서비스를 제공할 수 있습니다.
$ composer dump-autoload -o