메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

PEAR 자세히 살펴보기

한빛미디어

|

2002-05-29

|

by HANBIT

8,942

저자: Joao Prado Maia, 역 이호재

웹 애플리케이션을 제작하는 틀(framework)인 PEAR는 PEAR 표준 베이스 클래스(standard base PEAR classes)를 기반으로 만들어졌습니다. PEAR 표준 베이스 클래스는 이 클래스를 상속받는 클래스에게 기본적인 에러 처리 루틴과 필요한 변수, 상수를 제공합니다. 다시 말해 대부분의 PEAR 라이브러리와 패키지는 PEAR 표준 베이스 클래스의 서브클래스입니다.

PEAR 개발 팀은 표준 에러 처리 클래스를 만든 후 파괴자(destructor)를 에뮬레이션하는데 지대한 노력을 기울였습니다. PEAR 저장소에 있는 모든 파생 클래스에서 쓰여질 수 있도록 확장할 수 있게 만들어야 하기 때문입니다. PEAR 클래스에서 파괴자 에뮬레이션은 프로그래머에게 있어 매우 중요합니다. 왜냐하면 아직까지 PHP 자체는 클래스 파괴자를 지원하지 않기 때문입니다.

이는 새로운 PEAR 클래스에서 파괴자를 에뮬레이션하려면 자체적인 방법이 필요하다는 것을 의미합니다. 따라서 오브젝트가 사라지거나 필요하지 않을 때 또는 PHP 메모리 할당으로부터 제거될 때 특별한 함수를 실행시키는데 있어 특히 중요합니다.

표준 PEAR_Error 클래스

PEAR 클래스는 에러 루틴을 관리하기 위해 PEAR_Error 클래스를 사용해야 합니다. 물론 PEAR::DB에서도 PEAR_Error 클래스를 사용했습니다. PHP 4.0의 새로운 기능 중에 클래스를 인스턴스화 하지 않은 상태에서 클래스의 메소드를 호출할 수 있는 기능이 있습니다. PEAR_Error 클래스는 이러한 기능을 통해 정적으로 사용됩니다. 아래의 예제는 이러한 기능을 보여줍니다.

PEAR 패키지는 다른 중요한 PEAR 클래스처럼 다음과 같은 일을 합니다. 일반적으로 에러가 발생할 때 에러에 대한 몇몇 정보를 갖는 에러 오브젝트를 생성하기 위해 raiseError()를 호출합니다. PEAR::DB MySQL 드라이버에 대한 예제는 다음과 같습니다.
raiseError(DB_ERROR_CONNECT_FAILED, 
                               null, null, mysql_error());
    } elseif (empty($php_errormsg)) {
      return $this->raiseError(DB_ERROR_CONNECT_FAILED);
    } else {
      return $this->raiseError(DB_ERROR_CONNECT_FAILED, 
                          null, null, null, $php_errormsg);
    }
  }
?>
위의 코드는 실제로 MySQL 데이터베이스 서버로 성공적으로 연결되었는지를 검사합니다. ini_set()을 사용한 라인은 에러를 추적하는 PHP 기능을 작동시키고 $php_errormsg라는 특별한 변수에 에러를 저장하게 합니다. 이 특별한 변수는 다음 조건절에서 MySQL로 왜 제대로 연결되지 않았는지를 검사하기 위해 사용됩니다.

PEAR::DB 에러 처리

PEAR에 있어서 아주 훌륭한 특징 중 하나는 에러 처리 루틴입니다. PHP는 인터프리터 방식의 언어이기 때문에 에러는 보통 개발자가 생각하지 못했던 방식으로 사용자가 페이지를 볼 때 발생합니다. 시간에 쫒기는 개발자가 개인 사이트를 테스트할 때 그 사이트를 이용하는 사용자들로부터 사이트에 버그가 있다는 e-mail을 받는 일은 아주 일반적인 일이라고 볼 수 있습니다.

어떤 경우에 있어 문제의 원인은 데이터베이스 서버가 비정상적인 작동을 했기 때문일 수도 있고 코드 자체에 문제가 있기 때문일 수도 있습니다. PEAR 에러 처리에 있어 좋은 점 한가지는 그와 같은 간단한 에러를 얻어서 "죄송합니다. 현재 페이지에 기술적인 문제가 있습니다." 등을 나타내는 페이지를 보여주는 특별한 함수를 사용할 수 있다는 것입니다.

만약 PHP의 새로운 출력 버퍼링 함수를 이용해 PEAR 에러 처리를 한다면 이미 생성된 페이지를 캐시해서 에러 메시지만을 보여 줄 수도 있습니다. 다음을 살펴보도록 합시다.
 "mysql",
    "hostspec" => "localhost",
    "database" => "test_db",
    "username" => "scott",
    "password" => "wrong_password"
);

// PEAR 코드에서 발생하는 모든 에러를
//위에서 설정한 함수에서 처리하도록 설정합니다.
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK,
   "my_handle_error");
$dbh = DB::connect($dsn);

// 에러가 발생하지 않았다면 버퍼링된 페이지를 출력합니다.
ob_end_flush();
?>
주의: 이상의 출력 버퍼링 기능을 사용하기 위해서는 PHP 버전 4.0 이상을 사용해야 합니다.

위의 예제는 PEAR와 PHP 에러 처리 함수와 루틴을 사용하는 간단한 예에 지나지 않습니다. PHP가 겨우 5년밖에 안된 스크립트 언어라는 것을 고려해볼 경우 이 기술은 에러 기록에 있어 매우 뛰어난 기술이라고 할 수 있습니다.

PEAR::DB 클래스 팩토리

만약 PEAR DB 패키지가 어떻게 동작하는지 궁금해서 소스코드를 살펴보려 했다면 아마도 모든 데이터베이스 드라이버와 에러 처리 루틴 등의 클래스와 서브클래스를 다루는 방식을 보고 혼란스러웠을 것입니다. 여기에서 우리는 표준 PEAR_Error 클래스를 이해하고 PEAR 라이브러리가 에러에 관한 정보를 갖는 특별한 오브젝트를 생성하기 위해 PEAR_Error를 호출하는 방법에 대해 알아볼 것입니다. 이 외에도 PEAR::DB의 "팩토리(factory)" 메소드에 대해서도 살펴볼 것입니다. 이것은 PEAR::DB를 호출한 스크립트에서 런타임시 지정한 데이터베이스에 적절한 드라이버를 사용하기 위해 사용됩니다.

이 팩토리 메소드는 아주 간단해서 작동하는 방식만 한번 살펴보면 쉽게 이해할 수 있습니다. 다음 코드를 살펴보도록 하겠습니다.
 "mysql",
    "hostspec" => "localhost",
    "database" => "test_db",
    "username" => "scott",
    "password" => "tiger"
);
$dbh = DB::connect($dsn);
?>
호스트 정보, 데이터베이스 종류(MySQL, PostgreSQL 등), 데이터베이스 이름, 그리고 DB 클래스의 connect() 함수에 필요한 기타 다른 정보로 이루어져 있는 배열을 인자로 넘김으로써 위의 코드는 작동합니다. 여기서 적절한 서버에 접속하기 위해 정적 메소드를 사용하고 있다는 것에 한번 더 주목해 주시기 바랍니다.

DB의 connect() 메소드는 "팩토리" 메소드라고 불립니다. 이 메소드는 DB 서브디렉토리에서 적절한 PHP 파일을 포함하고 클래스 정의로부터 오브젝트를 인스턴스화합니다. 다음 코드를 살펴보도록 합시다.
connect($dsn);

        return $obj;
    }
}
?>
이는 파일을 포함하여 해당 데이터베이스의 고유한 connect() 메소드를 이용하여 데이터베이스에 접속하도록 합시다. 이것은 데이터베이스 핸들러를 리턴하는데, 이 핸들러는 DB_${type} 클래스의 메소드를 갖고 있는 오브젝트입니다(이번 예제에서는 DB_mysql 클래스).

드라이버를 이런 방식으로 다루는 것은 사용자가 데이터베이스 서버에 접속하기 위해 올바른 클래스와 함수를 알아야 하는 것보다 더 확실하면서 숙련된 방법이라고 할 수 있습니다. 그리고 이번 경우에서는 PEAR::DB 패키지를 사용하는 것이 좀 더 깔끔한 방법입니다. 그리고 이것은 추상화 라이브러리로 작동하며 데이터베이스가 작동하고 접속되는 방법입니다.

PEAR::DB 구조의 계층적 모습

PEAR::DB의 구조와 일반적 디자인은 모든 것이 잘 동작하고 확장 가능하도록 되어있습니다. PEAR::DB를 위한 새로운 드라이버를 생성하는 것은 어려운 일이 아닙니다. 이를 위해 해야 할 일은 새로운 드라이버를 생성하고 그것을 PEAR DB 서브디렉토리에 저장하는 것뿐입니다. 메인 DB 클래스에는 단지 패키지를 호출하는 프론트엔드 스크립트 한 줄만 수정함으로써 새로운 드라이버를 사용할 수 있습니다.
 "NEW_DATADASE_NAME_HERE",
    "hostspec" => "localhost",
    "database" => "test_db",
    "username" => "scott",
    "password" => "tiger"
);
?>
이 라이브러리는 매우 잘 디자인되어 있기 때문에 드라이버가 중요한 기능을 공유할 수 있도록 되었습니다. 이는 DB/common.php에 유틸리티 함수가 저장되어 있기 때문에 가능합니다. 이 파일은 다른 모든 데이터베이스 클래스가 상속받는 DB_common 클래스를 포함하고 있습니다. 아래를 코드를 참조하시기 바랍니다.

이와 같은 클래스 상속으로 인해 드라이버간에 코드를 재사용하는 것이 쉬워졌습니다. 그리고 이 유틸리티 클래스에서 찾을 수 있는 대부분의 함수와 메소드는 getRow(), numRows(), affectedRows()와 같은 표준 메소드입니다.

필자는 이 기사가 PEAR의 고급 코딩 기술에 있어 한 가닥 빛이 될 수 있기를 희망합니다. 그리고 이 기사로 인해 여러분이 PEAR 소스 코드를 좀 더 쉽게 이해할 수 있기를 바랍니다. 참고로 지금 이 기사의 내용이 이해하기 어렵다고 느끼시는 분은 PEAR 입문부터 읽어보시기 바랍니다.

Joao Prado Maia는 휴스턴에 살고 있는 웹 개발자입니다. 4년 이상 웹 기반의 애플리케이션을 개발했으며 새로운 기술과 프로그래밍 언어 배우는 것을 아주 좋아합니다.
TAG :
댓글 입력
자료실

최근 본 책0