싱글톤 패턴
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 91개 중 71번째.
싱글톤 패턴(Singleton Pattern)은 애플리케이션의 생명주기 동안 클래스에 단 하나의 인스턴스만 존재하도록 보장하는 생성 디자인 패턴입니다. 또한 해당 인스턴스에 대한 전역적인 접근 지점을 제공합니다.
이 패턴은 데이터베이스 연결, 설정 관리자 또는 로거와 같이 시스템 전체의 동작을 조정하기 위해 정확히 하나의 객체가 필요할 때 유용합니다. 이러한 객체의 인스턴스를 여러 개 생성하는 것은 리소스를 낭비하거나 일관성 없는 동작을 유발할 수 있습니다.
PHP에서 싱글톤(Singleton)을 구현하는 방법은 다음과 같습니다:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// 프라이빗 생성자는 직접적인 인스턴스화를 방지합니다
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
출력:
Same instance이 패턴은 세 가지 핵심 요소에 의존합니다: new를 직접 사용하는 것을 방지하는 프라이빗 생성자, 단일 인스턴스를 보유하는 정적 속성, 그리고 첫 번째 호출 시 인스턴스를 생성하고 이후 호출 시에는 이를 반환하는 정적 메서드입니다.
싱글톤을 진정으로 견고하게 만들려면, 복제(cloning)와 역직렬화(unserialization)도 방지해야 합니다:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
챌린지
쉬움싱글톤 패턴(Singleton Pattern)을 사용하여 설정 관리자(configuration manager)를 만들어 보겠습니다. 실제 애플리케이션에서는 일반적으로 설정 값에 대해 단일 소스(single source of truth)를 유지하기를 원합니다. 여러 개의 설정 객체가 존재하면 시스템 전체에서 일관성 없는 동작이 발생할 수 있기 때문입니다.
코드는 두 개의 파일로 구성됩니다:
Config.php— 싱글톤 패턴을 구현하는Config클래스를 생성합니다. 설정 관리자는 다음 사항을 충족해야 합니다:- 설정값들을 private 배열 프로퍼티에 저장합니다.
- 설정 배열을 빈 상태로 초기화하는 private 생성자를 가집니다.
- 단일 인스턴스를 반환하는 static
getInstance()메서드를 제공합니다. __clone()을 private으로 만들어 복제를 방지합니다.- 설정을 저장하기 위한
set(string $key, string $value): void메서드를 포함합니다. - 키에 해당하는 값을 반환하거나, 키가 존재하지 않으면
null을 반환하는get(string $key): ?string메서드를 포함합니다. - 모든 설정을 반환하는
getAll(): array메서드를 포함합니다.
main.php— Config 파일을 포함합니다. 입력으로 키(key)와 값(value) 두 가지를 받게 됩니다.Config 인스턴스를 가져와서 키
"app_name"과 값"MyApp"으로 기본 설정을 저장합니다.Config 인스턴스에 대한 두 번째 참조를 가져오고(다시
getInstance()사용), 입력받은 키와 값을 사용하여 또 다른 설정을 저장합니다.마지막으로 싱글톤이 올바르게 작동하는지 확인합니다:
- 두 참조가 동일한 객체를 가리키는지 여부에 따라
"Same instance: true"또는"Same instance: false"를 출력합니다 (비교를 위해===를 사용하세요). - 저장된 총 설정 개수를 보여주는
"Settings count: [count]"를 출력합니다 (getAll()결과에count()를 사용하세요). - 두 번째 참조를 통해 가져온 app_name 설정을 보여주는
"App name: [value]"를 출력합니다.
- 두 참조가 동일한 객체를 가리키는지 여부에 따라
이 챌린지는 싱글톤 패턴의 핵심적인 이점을 보여줍니다. getInstance()를 몇 번 호출하든 항상 동일한 객체를 얻게 되므로, 애플리케이션의 모든 부분이 동일한 설정 상태를 공유하게 됩니다.
치트 시트
싱글톤 패턴(Singleton Pattern)은 애플리케이션의 수명 주기 동안 클래스에 단 하나의 인스턴스만 존재하도록 보장하며, 해당 인스턴스에 대한 전역적인 접근 지점을 제공합니다.
이 패턴은 데이터베이스 연결, 설정 관리자 또는 로거와 같이 여러 인스턴스가 생성될 경우 리소스가 낭비되거나 일관성 없는 동작을 유발할 수 있는 객체에 유용합니다.
기본적인 싱글톤 구현:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// 프라이빗 생성자는 직접적인 인스턴스화를 방지합니다
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
// 출력: Same instance
주요 요소:
- 프라이빗 생성자(Private constructor) —
new를 직접 사용하는 것을 방지합니다 - 정적 속성(Static property) — 단일 인스턴스를 보유합니다
- 정적 메서드(Static method) — 첫 번째 호출 시 인스턴스를 생성하고 이후 호출 시에는 기존 인스턴스를 반환합니다
복제 및 역직렬화 방지:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
직접 해보기
<?php
require_once 'Config.php';
// 입력 읽기
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Config 인스턴스를 가져오고 "app_name"을 "MyApp"으로 설정합니다.
// TODO: getInstance()를 다시 사용하여 Config에 대한 두 번째 참조를 가져옵니다.
// TODO: 두 번째 참조를 사용하여 입력받은 $key와 $value로 설정을 지정합니다.
// TODO: 싱글톤이 작동하는지 확인합니다:
// - === 비교를 기반으로 "Same instance: true" 또는 "Same instance: false"를 출력합니다.
// - 전체 설정 수를 보여주는 "Settings count: [count]"를 출력합니다.
// - 두 번째 참조를 통해 검색된 app_name을 보여주는 "App name: [value]"를 출력합니다.
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8매직 메서드
매직 메서드 소개__toString 및 __debugInfo__get, __set, __isset, __unset__call 및 __callStatic__clone 및 객체 복제__serialize 및 __unserialize요약 - 커스텀 컬렉션