PHP Autoload
이번 포스팅에서는 PHP의 Autoload에 대해서 알아 보려고 합니다.
PHP의 Autoload를 쓰기 위해서는 먼저 객체지향 프로그래밍에 대해 알고 있어야 합니다.
여기서 객체지향 프로그래밍 언어에 대해 논하지 않습니다.
(제 실력이 객체지향 언어를 논할 정도로 깊지 않고, 설명하려는 PHP의 Autoload와도 거리가 멀기 때문입니다.)
하루 일상을 클래스들로 표현해 보도록 하겠습니다.
아침에 출근하면 우리는 인사 부터 합니다.
그래서 우선 간단한 Hello class를 먼저 만들어 봅시다.
Hello.php
<?php
class Hello
{
public function say()
{
echo "Hello- PHP!";
}
}
그런데 주소창에 localhost:8080/Hello.php 를 아무리 날려보아도 아무것도 나오지 않습니다.
어디에서도 Hello class를 객체화 하여 say 라는 method를 호출하지 않기 때문입니다.
그럼 어디에선가는 위의 클래스를 불러 호출할 녀석이 필요 합니다.
index.php
<?php
require_once 'Hello.php';
$sayHello = new Hello();
$sayHello->say();
가장 상단에 Hello 클래스가 들어 있는 Hello.php 파일을 require_once 하였습니다.
그리고 아래줄에 Hello를 객체로 선언해서 say method를 호출하는 것을 볼 수 있습니다.
index.php를 호출하면 이제 화면에 "Hello- PHP!" 가 출력되는 것을 볼 수 있습니다.
인사를 했으니 이제 다른 일을 하려고 합니다.
그래서 Task01 클래스를 만들었습니다.
Task01.php
<?php
class Task01
{
public function todoTask()
{
echo "todo Task!";
}
}
이제 첫번째 할일이 있는 클래스를 만들었습니다.
아... 그런데 깜빡할 뻔했습니다.
저렇게 단독으로 있는 클래스들은 혼자 실행을 할 수가 없죠
반드시 어딘가에서 불러 줘야 합니다.
그래서 index.php 에서 Task01.php 를 상단에 require_once 로 불러오고
아래에서 객체를 생성해 메소드를 불러 옵니다.
index.php 수정
<?php
require_once 'Hello.php';
require_once 'Task01.php';
$sayHello = new Hello();
$sayHello->say();
echo '<br>';
$task01 = new Task01();
$task01->todoTask();
이제 추가 했던 작업이 화면에 정상적으로 보여 집니다.
그런데 일은 이것만 있는게 아닙니다.
일이 계속 해서 생겨 납니다.
Task03, Task04, Task05........................
수많은 일이 발생하고 있습니다.
많은 일(class)를 실행하기 위해서는 객체화 시키는 작업(new class명)은 어쩔 수 없습니다.
일을 시켜야 하니까요.
그런데 늘어 나는 일에 비례해서 require_once 를 언제까지 써줘야 할까요.
만약에 모든 클래스를 require_once로 등록해 놨는데
그중에 안하는 일이 생긴다면?
혹은 애써 다 등록해 놨다고 생각했는데 실수로 빠트렸거나
중간에 오타가 있어서 제대로 클래스를 불러오지 않는다면???
모두 실행이 안되고 객체를 생성할 수 없다는 에러를 뿌리게 됩니다.
그럼 이제 왜 Autoload 가 필요한지 감을 잡으셨을 겁니다.
Autoload 는 사용자가 정의하지 않는 클래스를 만나면 자동으로 해당 파일을 불러 들이기 위해 사용합니다.
그럼 상단에 있는 수만은 require_once 를 싹다 제거 할 수 있겠죠.
거기다 오타나 실수로 빠트린 클래스에 대한 걱정도 사라지게 됩니다.
그럼 이제 한 번 autoload를 써봅시다!!
index.php에 다음과 같이 수정 합니다.
index.php 수정
<?php
// require_once 'Hello.php';
// require_once 'Task01.php';
spl_autoload_register('my_autoloader');
$sayHello = new Hello();
$sayHello->say();
echo '<br>';
$task01 = new Task01();
$task01->todoTask();
function my_autoloader($class)
{
echo 'class :'.$class;
}
기존에 있던 require_once 문장은 모두 주석 처리 하였습니다.
대신 spl_autoload_register() 과 function my_autoloader() 함수를 추가 하였습니다.
여기서 주위할 점은 spl_autoload_register이 가장 먼저 나와야 한다는 것입니다.
그리고 또 한가지 주위해야 할 점은 spl_autoload_register에 들어갈 값은
function 다음에 올 이름과 똑같아야 한다는 점입니다. 어떤 이름을 쓰던 상관이 없지만 저 둘은 똑같아야 합니다.
여기서는 모두 my_autoloader 라는 이름을 사용했습니다.
위와 같이 하고 실행을 해봅시다.
호출하려 했던 클래스의 이름이 나오고 에러를 발생합니다.
Hello라는 클래스를 불러 올 수 없다는 에러 입니다.
autoload를 사용했다고 자동으로 클래스를 불러 오는 것은 아닙니다.
사실 autoload안에 불러올 내용은 우리가 직접 만들어 넣어 주어야 합니다.
내용을 불러오기 위해 my_autoloader 함수 안에 require_once 를 한 번 사용합니다.
index.php 수정
<?php
// require_once 'Hello.php';
// require_once 'Task01.php';
spl_autoload_register('my_autoloader');
$sayHello = new Hello();
$sayHello->say();
echo '<br>';
$task01 = new Task01();
$task01->todoTask();
function my_autoloader($class)
{
echo 'class :'.$class;
require_once $class.'.php';
}
require_once $class.'.php';
라는 문장을 추가해 주었습니다.
위에 출력된 메시지를 보면 알수 있듯이
autoload를 실행하게 되면 클래스명이 전달되게 됩니다.
우리는 모든 파일명을 클래스명과 동일하게 작성하였으므로
클래스명.'.php'; 가 되도록 문장을 만들어 넣어 주었습니다.
- 보통 하나의 파일에는 하나의 클래스가 존재하며
- 클래스 명과 파일명을 동일하게 작성합니다.
이것을 조금 더 다듬어 보도록 하겠습니다.
요즘 '핫'하게 쓰이는 익명함수 방식을 사용합니다.
index.php 수정
<?php
spl_autoload_register(function ($class){
require_once $class.'.php';
});
$sayHello = new Hello();
$sayHello->say();
echo '<br>';
$task01 = new Task01();
$task01->todoTask();
function my_autoloader() 함수 부분을 spl_autoload_register의 인자 부분으로 집어 넣었습니다.
그리고 my_autoloader 이라는 함수명을 제거해 버렸습니다. 물론 echo 도 지웠구요.
그리고 다시 실행해 봅니다.
어떤가요?
제대로 동작되지요?
index.php 파일의 내용이 처음보다 간결해 졌습니다.
만약 클랙스가 100 개라면 require_once 역시 100줄 들어 가야 했을텐데 3줄로 끝나 버렸습니다.
그런데 아직 조금 더 줄이고 싶습니다.
autoload 부분을 다른 파일로 분리시켜
autoload 파일을 삽입하는 방식으로 전화 시켜 봅니다.
vender/autoload.php
<?php
spl_autoload_register(function ($class){
require_once $class.'.php';
});
vender 이라는 폴더를 새로 하나 만들고 그 아래 autoload.php 파일을 만들어
autoload 관련된 익명 함수만 구현해 놓았습니다.
index.php 수정
<?php
require_once 'vender/autoload.php';
$sayHello = new Hello();
$sayHello->say();
echo '<br>';
$task01 = new Task01();
$task01->todoTask();
상단에 require_once 로 autoload 파일을 불러 옵니다.
이제 상당히 깔끔해 졌습니다.
php의 autoload 는 이렇게 사용자가 원하는 방식으로 구현이 가능합니다.
실제 업무에서는 클래스 파일이 여러 디렉토리와 파일에 나누어져 있기 때문에
위의 autoload 만으로는 처리할 수 없습니다.
따라서 그에 맞게 수정을 해줘야 합니다.
다음 포스팅에서는 namespace를 어떻게 autoload 에 적용하는지에 대해 정리해 보겠습니다.
참고자료 : PHP spl_autoload_register 매뉴얼, 생활코딩
제 글을 공유하시거나 인용하실 때는 출처를 남겨주세요.
이 포스팅의 소스는 깃허브(https://github.com/freehoon/workspace/tree/master/phpAutoloadSample2)에 공개 되어 있습니다.
'개발 > PHP' 카테고리의 다른 글
MVC모델을 적용한 블로그(게시판) 만들기 - 3. Model (DB 처리 하기) (0) | 2018.06.26 |
---|---|
MVC모델을 적용한 블로그(게시판) 만들기 - 2. Controller (0) | 2018.06.26 |
MVC모델을 적용한 블로그(게시판) 만들기 - 1. Front Controller(요구사항 받아들이기) (3) | 2018.06.21 |
MVC모델을 적용한 블로그(게시판) 만들기 - 0.개념 정리 및 준비하기 (0) | 2018.06.21 |
PHP Autoload와 namespace (3) | 2018.06.21 |