개발 지식

개발 지식

PHP PHP에서 상태 패턴(State Pattern) 활용 예시

페이지 정보

profile_image
영삼이
0건 206회 25-03-28 23:18

본문

✅ PHP에서 상태 패턴(State Pattern) 활용 예시

상태 패턴은 객체의 내부 상태에 따라 행동을 바꾸는 디자인 패턴입니다. 조건문 없이 상태별 클래스를 분리해 유지보수성과 확장성을 높일 수 있습니다. 워크플로우, 주문 상태, 게시글 상태 등 다양한 실무 시나리오에 적합합니다.


🎯 문제 상황 예시

[code=php]
class Order {
    private string $status = 'new';

    public function next() {
        if ($this->status === 'new') {
            $this->status = 'paid';
        } elseif ($this->status === 'paid') {
            $this->status = 'shipped';
        } elseif ($this->status === 'shipped') {
            $this->status = 'delivered';
        }
    }
}
[/code]
  • 조건문이 늘어나며 유지보수 어려움

  • 새로운 상태 추가 시 if-else 지옥


✅ 상태 패턴 구조로 개선

1. 상태 인터페이스 정의

[code=php]
interface OrderState {
    public function next(OrderContext $order): void;
    public function getName(): string;
}
[/code]

2. 상태별 클래스 정의

[code=php]
class NewOrder implements OrderState {
    public function next(OrderContext $order): void {
        $order->setState(new PaidOrder());
    }

    public function getName(): string {
        return '신규 주문';
    }
}

class PaidOrder implements OrderState {
    public function next(OrderContext $order): void {
        $order->setState(new ShippedOrder());
    }

    public function getName(): string {
        return '결제 완료';
    }
}

class ShippedOrder implements OrderState {
    public function next(OrderContext $order): void {
        $order->setState(new DeliveredOrder());
    }

    public function getName(): string {
        return '배송 중';
    }
}

class DeliveredOrder implements OrderState {
    public function next(OrderContext $order): void {
        // 마지막 상태
    }

    public function getName(): string {
        return '배송 완료';
    }
}
[/code]

3. 컨텍스트 클래스

[code=php]
class OrderContext {
    private OrderState $state;

    public function __construct() {
        $this->state = new NewOrder();
    }

    public function setState(OrderState $state): void {
        $this->state = $state;
    }

    public function next(): void {
        $this->state->next($this);
    }

    public function getStatus(): string {
        return $this->state->getName();
    }
}
[/code]

🚀 사용 예시

[code=php]
$order = new OrderContext();

echo $order->getStatus(); // 신규 주문
$order->next();

echo $order->getStatus(); // 결제 완료
$order->next();

echo $order->getStatus(); // 배송 중
[/code]

✅ 장점

항목 상태 패턴 조건문 방식
확장성 ✅ 좋음 ❌ 나쁨
책임 분리 ✅ 상태 클래스 별도 관리 ❌ 로직 집중됨
테스트 용이성 ✅ 상태 단위 테스트 가능 ❌ 상태 분리 불가능

🧠 요약

  • 상태 패턴은 조건문 없이 상태 전이를 관리할 수 있는 객체지향 설계

  • 주문, 결제, 게시글 등 상태 기반 로직에서 매우 유용

  • 각 상태를 클래스로 분리해 유연한 확장 구조 구현 가능


✅ PHP 프로젝트에서 이벤트 기반 아키텍처 적용하기

이벤트 기반 아키텍처는 코드의 결합도를 낮추고, 확장성과 유지보수성을 극대화하는 구조입니다. PHP에서도 Symfony EventDispatcher 같은 도구 없이 순수하게 이벤트 시스템을 구현할 수 있습니다.


📦 기본 개념

  • 이벤트(Event): 어떤 일이 발생했음을 표현하는 객체

  • 리스너(Listener): 이벤트에 반응하는 실행 코드

  • 디스패처(Dispatcher): 이벤트를 발생시키고, 등록된 리스너에게 알림


🧱 이벤트 객체 정의

[code=php]
class UserRegisteredEvent {
    public function __construct(public string $email) {}
}
[/code]

🔔 리스너 클래스 정의

[code=php]
class SendWelcomeEmail {
    public function handle(UserRegisteredEvent $event): void {
        echo "환영 이메일 전송: {$event->email}\n";
    }
}

class LogUserRegistration {
    public function handle(UserRegisteredEvent $event): void {
        echo "사용자 등록 로그 기록: {$event->email}\n";
    }
}
[/code]

🧰 간단한 디스패처 구현

[code=php]
class EventDispatcher {
    private array $listeners = [];

    public function listen(string $event, callable $listener): void {
        $this->listeners[$event][] = $listener;
    }

    public function dispatch(object $event): void {
        $eventClass = get_class($event);
        foreach ($this->listeners[$eventClass] ?? [] as $listener) {
            $listener($event);
        }
    }
}
[/code]

🚀 이벤트 등록 및 실행

[code=php]
$dispatcher = new EventDispatcher();

$dispatcher->listen(UserRegisteredEvent::class, [new SendWelcomeEmail(), 'handle']);
$dispatcher->listen(UserRegisteredEvent::class, [new LogUserRegistration(), 'handle']);

$dispatcher->dispatch(new UserRegisteredEvent('kim@example.com'));
[/code]

✅ 장점

  • 리스너는 이벤트에만 반응, 호출자는 리스너 존재를 몰라도 됨

  • 새로운 기능 추가 시 기존 코드 변경 없이 리스너만 추가

  • 테스트와 디커플링에 매우 유리


🧠 요약

  • 이벤트 기반 아키텍처는 확장성과 유지보수성을 극대화

  • PHP에서도 간단한 디스패처로 적용 가능

  • 실무에서는 회원가입, 주문 처리, 알림 전송 등에 자주 사용


댓글목록

등록된 댓글이 없습니다.