Singleton pattern in PHP

Development 의견 남기기

오늘 RSS를 훓어보다 자주가는 개발자 커뮤니티에 다음과 같은 질문이 올라온것을 보았다.

“PHP에서의 Singleton pattern”

마침 몇일전 새로온 개발자와 singleton pattern에 대해 이야기했기에 아래와 같이 답변을 달았다.

질문

알맞게 Singleton pattern을 쓰면 퍼포먼스가 향상되는걸로 알고있습니다.
그런데 PHP는 request마다 자동으로 thread를 할당시키므로 Memory Sharing이 안되는걸로 아는데요,
Singleton pattern이 의미가 있나요?


답변

싱글톤을 사용하는 목적에는 퍼포먼스 향상도 있지만 객체의 안전한 사용도 있습니다.

쉬운예로
database에 접속하는 db 라는 객체의 경우 쿼리가 많더라도 연결(connect)은 한번만 되는게 맞습니다. 하지만 클래스나 함수내에서 database 에 쿼리를 넣을때마다 매번 db 객체를 생성(new)하면 매번 연결되겠죠. 이럴경우 이미 생성된 db 객체를 싱글톤으로 받으면 최초 한번 생성된 객체를 사용하여 database 에 접근할 수 있습니다.

물론 database 연결같은 경우 언어차원에서 최적화된 방법을 제공하기도해서 임의의 싱글톤사용이 퍼포먼스를 크게 향상시킨다고 단정할 순 없지만
db에 요청된 쿼리의 분석같은 단일객체를 유지하는게 필수적인 경우 유용합니다. 전역변수로 생성하거나 해당 객체를 매번 클래스마다 건네받기에는 코드의 안정성이나 효율문제도 있고 확장의 문제도 있겠죠.

질문에 대한 직접적인 답변을 하라면,
한번의 request동안 진행되는 여러개의 프로세스에서 싱글톤으로 사용하기 위함. 정도라고보면 되겠네요.

여기까지가 내가 답변한 내용이었는데, 약간의 이해를 돕기 위해 포스트로 남긴다.
singleton pattern 은 프로그램이 실행하는데 딱 한개의 객체만이 생성되야할때 사용하는 방법으로 가장 기본적인 디자인패턴중 하나이다. 위에 답변한 database 관련된 내용을 코드와 함께 설명한다면 다음 정도가 되겠다.

일반적인 클래스로 객체를 생성하여 사용한다면 다음과 같이 사용할 수 있다.

class DB {
    public function __construct() {
        $this->connect();
    }
 
    public function connect() {
        // database connect
    }
 
    public function query($query) {
        // query
    }
 
}
 
$db = new DB;
$db->query("SELECT * FROM table");

아무 문제 없어보인다. 하지만 이 클래스는 객체를 생성할때마다 connect() 를 실행하기 때문에 여러곳에서 사용하려면 여러번의 database 연결이 불가피해진다. 웹어플리케이션에서 db 사용에 있어 가장 큰 비용이 connection임을 고려한다면 심각한 문제이다. 뿐만 아니라 퍼포먼스를 차치하더라도 필요한 구현 자체가 힘들거나 불가능해질 수 있다. 예를 들어 database에 질의된 모든 쿼리들의 수행시각을 뽑아내려고 할때 여러개의 객체에서 각각의 쿼리를 처리한다면 모든 객체를 뒤져서 수행시각을 뽑아내야할것이다.

자 그럼 어떻게 하면 좋을까?
db 객체를 생성할때 이미 만들어놓은(database 에 연결된) 객체가 있다면 그것을 사용하여 쿼리를 처리하도록 하면 된다. 이게 바로 singleton pattern 의 핵심이다.
코드로 구현하면 다음정도가 된다.

class DB {
    private function __construct() {
        $this->connect();
    }
 
    private function connect() {
        // database connect
    }
 
    public function &getInstance() {
        static $instances = array();
        if( !array_key_exists( 'DB' , $instance ) ) {
            $instances['DB'] = new DB;
        }
        $instance =& $instances['DB'];
        return $instance;
     }
 
    public function query($query) {
        // query 
    }
 
}
 
$db = DB::getInstance();
$db->query("SELECT * FROM table");

이렇게 하면 어디서든 DB::getInstace() 메소드를 통해 유일한 database resource를 사용할 수 있다.
또한 전역변수로 설정하거나 DB 클래스를 직접 상속받지 않아도 다음과 같이 다른 클래스 내부에서 사용할 수 있기때문에 안정성 및 확정성도 좋아지게 된다.

class MyCar {
    function getModel() {
        $db = DB::getInstance();
        $db->query("SELECT * FROM table");
    }
}

이렇듯 singleton pattern 을 잘 응용하면 많은 성능향상과 확장성을 잡을 수 있기 때문에 객체지향적인 프로그래밍에서는 필수적인 기술이다. 물론 singleton pattern 을 몰라도 비슷하게 구현해 낼 수 있을지 모른다. 하지만 이것은 내 작업실에 ‘포크레인’이 있음에도 그 사실을 몰라 ‘삽질’하는 것과 마찬가지아닐까. 이것이 바로 디자인 패턴의 힘이다.

그리고..
이 포스트를 작성하는 진짜 이유, 내가 하고 싶은 이야기는 이제부터다.
PHP로 10년이상 프로젝트를 수행해오면서 수많은 개발자를 만났다. 그중 실력자들도 있었지만 경력에 비해 기본이 조금 부족하지 않나 싶은 개발자도 적지 않았다. 특히 이번에 새로 작업을 맡긴 개발자의 경우 실무 경력이 5년이 넘어가지만 singleton pattern 을 포함한 디자인패턴에 대한 이해가 전혀 없었다. 물론 디자인패턴을 많이 안다고 실력이 좋고, 모른다고 실력이 없다고 할수는 없지만 “아는 만큼 효율적인 것” 이 바로 소프트웨어 개발, 특히 코딩이다.

자바나 C++ 같은 태생이 객체지향인 언어들로 프로그래밍을 배운경우 입문서적부터 객체지향적인 사고를 강조하고 객체에 대해서 이해시키도록 하기때문에 자연스럽게 이런 개념과 스킬을 습득하는 편이지만 PHP의 경우 PHP가 적극적으로 사용되기시작한 시점(PHP3 과 PHP4) 에서는 객체지향적인 언어가 아니었기 때문에 그당시 공부를 하였거나 그때 만들어진 소스로 공부를 한 사람은 PHP로 객체지향적인 사용을 잘 하지 못하는 경향이 있다. 심지어 최근 서적에서조차 PHP를 단순한 순차적 인터프리터 정도로만 설명하고 그런 방식의 사용을 종용한다.

이제 PHP 언어는 객체지향 언어라고 불러도 좋을만큼 객체지향 프로그래밍을 하는데 필요한 요소를 제공한다. 객체, 클래스, 메서드등은 물론 인스턴스, 상속, 캡슐화, 추상화 개념도 잘 구현해놓았으며 최근에는 네임스페이스와 같은 기능도 도입되면서 대규모 프로젝트에서의 설계/구현에 있어서 부족함이 없다. 그런만큼 PHP 개발자들은 이런 개념과 기능을 빨리 습득하여 좀더 견고하고 유지보수가 쉬운 소프트웨어를 만들었으면 하는 바램이다.

의견을 남겨주세요

Trackback URL : http://blueruin.org/archives/500/trackback

WP Theme & Icons by N.Design Studio
Entries RSS Log in