PHP에서 상태 패턴(State Pattern) 활용 예시 > 개발 지식 | 영삼넷

개발 지식

개발 지식

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

페이지 정보

profile_image
영삼이
0건 4,644회 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에서도 간단한 디스패처로 적용 가능

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


댓글목록

등록된 댓글이 없습니다.