생성 패턴: 팩토리, 빌더, 싱글턴
생성 패턴으로 객체 생성을 깔끔하게 제어합니다.
생성 패턴: 팩토리, 빌더, 싱글턴은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
생성 제어
생성 패턴은 필요한 것과 그것을 구축하는 방법을 분리합니다. 생성 과정이 조건부이거나 여러 단계로 이루어지거나 중앙 집중화되어야 할 때 코드베이스 곳곳에 new를 흩뿌리면 호출자가 구체 클래스에 결합됩니다. 여기서는 팩토리(및 팩토리 메서드), 복잡한 조립을 위한 빌더, 그리고 싱글턴(주의할 점 포함)을 다룹니다.
단순 팩토리
단순 팩토리는 하나의 메서드 뒤에 생성 결정을 중앙 집중화합니다. 호출자는 논리적 유형을 요청하고 설정이 완료된 구체 인스턴스를 받으므로, 클래스 이름을 알 필요가 없습니다.
<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
public function send(string $m): string { return "sms: $m"; }
}
final class NotifierFactory {
public static function make(string $channel): Notifier {
return match ($channel) {
'email' => new EmailNotifier(),
'sms' => new SmsNotifier(),
default => throw new InvalidArgumentException($channel),
};
}
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;
팩토리 메서드
팩토리 메서드 패턴은 인스턴스화를 하위 클래스에 위임합니다. 기본 클래스는 추상 create()를 호출하는 알고리즘을 정의하고, 각 하위 클래스가 구체적인 제품을 결정합니다. 이는 OCP에 부합합니다. 기존 생성 주체를 수정하지 않고 새 생성 주체를 추가할 수 있습니다.
<?php
abstract class ReportExporter {
abstract protected function create(): string;
public function export(): string {
return 'Exported as ' . $this->create();
}
}
final class PdfExporter extends ReportExporter {
protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;
추상 팩토리
추상 팩토리는 함께 사용해야 하는 관련 객체의 제품군을 생성합니다(예: MySqlConnection + MySqlQueryBuilder). 하나의 팩토리가 전체 집합을 제공하므로 각 부분이 호환된다는 점을 보장합니다. 제품군이 내부적으로 일관성을 유지해야 할 때 사용하십시오.
빌더: 문제점
객체에 선택적 매개변수가 많이 필요하면 생성자가 읽기 어려운 위치 인수 목록이나, PHP에는 아예 존재하지 않는 단계적 오버로드로 부풀어 오릅니다. 빌더 패턴은 복잡한 객체를 단계별로 조립하고 마지막에 완성된 유효한 제품을 반환합니다.
플루언트 빌더
플루언트 빌더는 각 설정 메서드에서 $this를 반환하고, 그다음 build()가 불변 결과를 생성합니다. 이를 통해 제품 자체는 단순하게 유지하고 조립 로직을 빌더로 옮길 수 있습니다.
<?php
final class Query {
public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
private string $table = '';
private array $where = [];
public function from(string $t): self { $this->table = $t; return $this; }
public function where(string $c): self { $this->where[] = $c; return $this; }
public function build(): Query {
$sql = "SELECT * FROM {$this->table}";
if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
return new Query($sql);
}
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;
빌더와 이름 있는 생성자 비교
더 단순한 경우에는 PHP 8의 이름 있는 인수와 이름 있는 생성자(정적 팩토리 메서드)가 완전한 빌더보다 나은 경우가 많습니다.
- 모든 데이터를 한 번에 사용할 수 있으면 이름 있는 인수를 사용하십시오.
- 조립이 여러 단계이거나 조건부이거나 여러 호출 지점에서 재사용되면 빌더를 사용하십시오.
<?php
final class Money {
private function __construct(public readonly int $cents, public readonly string $cur) {}
public static function fromDollars(float $d): self {
return new self((int) round($d * 100), 'USD');
}
public static function zero(string $cur = 'USD'): self {
return new self(0, $cur);
}
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)
싱글턴
싱글턴은 전역 접근 지점과 함께 하나의 인스턴스만 존재하도록 보장합니다. 비공개 생성자와 정적 접근자를 사용해 구현합니다. 프로세스 안에서 반드시 유일해야 하는 대상에는 실제로 유용하지만, 가장 많이 남용되는 패턴이기도 합니다.
<?php
final class Config {
private static ?self $instance = null;
private array $data = ['debug' => true];
private function __construct() {}
public static function instance(): self {
return self::$instance ??= new self();
}
public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true
싱글턴이 문제를 일으키는 이유
싱글턴은 숨겨진 전역 상태를 도입합니다. 호출자가 의존성을 선언하는 대신 Config::instance()에 직접 접근하므로 테스트 가능성과 병렬 실행이 깨집니다. 현대 PHP에서는 DI 컨테이너에 하나의 공유 인스턴스를 등록하고(“단일 인스턴스” 수명 주기), 이를 주입하는 방식을 선호하십시오. 전역 결합 없이 하나의 인스턴스를 얻을 수 있습니다.
적절한 도구 선택하기
- 단순 팩토리/팩토리 메서드: 생성 결정 뒤에 구체 클래스를 숨깁니다.
- 추상 팩토리: 호환되는 제품군을 생성합니다.
- 빌더: 복잡한 객체를 단계별로 조립합니다.
- 싱글턴: 최후의 수단으로 사용하고, 컨테이너가 관리하는 공유 서비스를 우선하십시오.
네 가지 모두 구체 생성자에 대한 결합을 줄여 코드를 더 쉽게 확장하고 테스트할 수 있게 합니다.
레지스트리 기반 팩토리
더 동적인 팩토리는 레지스트리에서 생성 주체를 조회하므로, 팩토리를 수정하지 않고도 새 유형이 스스로 등록할 수 있습니다(진정한 OCP). 플러그인 시스템과 직렬화 도구가 런타임에 유형 이름을 생성자로 해석하는 방식이 바로 이와 같습니다.
<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }
final class ShapeRegistry {
private array $creators = [];
public function register(string $key, callable $factory): void {
$this->creators[$key] = $factory;
}
public function create(string $key): Shape {
return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
}
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square
빠른 확인
이 시나리오에 가장 적합한 생성 도구를 선택하십시오.
복습
생성 패턴을 사용해 객체 생성을 제어했습니다. 팩토리로 구체 유형을 숨기고 제품군을 선택했으며, 빌더로 복잡한 객체를 유연하게 조립하고, 싱글턴의 장단점도 살펴보았습니다. 현대적인 결론은 다음과 같습니다. 팩토리와 빌더는 자유롭게 사용하되, 싱글턴은 DI 컨테이너의 공유 인스턴스 수명 주기로 대체하여 의존성을 명시적이고 테스트 가능하게 유지하십시오.
자주 묻는 질문
“생성 패턴: 팩토리, 빌더, 싱글턴” 강의는 무료인가요?
네 — “생성 패턴: 팩토리, 빌더, 싱글턴” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“생성 패턴: 팩토리, 빌더, 싱글턴”에서 뭘 배우나요?
생성 패턴으로 객체 생성을 깔끔하게 제어합니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
PHP Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“생성 패턴: 팩토리, 빌더, 싱글턴” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- SOLID 원칙 실전
- 생성 패턴: 팩토리, 빌더, 싱글턴
- 구조 패턴: 어댑터, 데코레이터, 퍼사드
- 행동 패턴: 전략, 옵서버, 커맨드