1. 개요
1-1. Laravel에서 전략 패턴 적용 목적
- 여러 알고리즘 및 동작 방식 중 변화 가능성이 높은 부분을 인터페이스로 추상화하여, 실행 시점에 적절한 전략을 선택할 수 있도록 합니다.
- 이를 통해 코드의 유연성, 확장성 및 유지보수성을 크게 향상시킬 수 있습니다.
1-2. 핵심 개념
- **전략 패턴(Strategy Pattern)**은 런타임 중에 알고리즘을 변경할 수 있도록 설계하는 행동 디자인 패턴입니다.
- 전략은 여러 알고리즘 또는 기능을 추상화한 “행동 계획”으로, 필요에 따라 전략을 교체하여 동작을 전환할 수 있습니다.
2. 전략 패턴 개념 정리
2-1. 정의
전략 패턴은 클라이언트에서 사용할 알고리즘 또는 기능을 전략(Strategy) 인터페이스로 정의하고, 구체적인 구현은 별도의 전략 객체로 작성하여 실행 시점에 동적으로 선택하여 사용하는 디자인 패턴입니다.
2-2. 전략의 역할
- 전략(Strategy): 알고리즘 또는 기능을 추상화한 객체
- 컨텍스트(Context): 클라이언트의 요청을 받아 전략 객체를 이용하여 행동을 수행하는 객체
- 클라이언트(Client): 전략을 사용하는 사용자 코드
3. 적용 예시
3-1. 실제 적용 시나리오
- 결제 수단 선택: 카카오페이, 카드, 포인트 등 다양한 결제 방식 지원
- 알림 전송: Slack, Email, SMS 등 메신저를 통한 알림 전송
- 정렬/필터 알고리즘: 데이터 정렬이나 필터링 알고리즘 전환
- 이미지 인코딩/압축: 다양한 이미지 처리 방식 적용
3-2. Laravel 기반 예제 - NotificationService
Laravel 환경에서 NotificationService를 예로 들면, 여러 알림 전송 방법(메신저)이 존재할 때 전략 패턴을 사용해 메시지를 전송하는 방식을 구현할 수 있습니다.
4. 전략 패턴 코드 예시 (Laravel 기준)
4-1. 전략 인터페이스 정의
interface MessengerInterface {
public function send(string $message): bool;
}
4-2. 구체 전략 클래스 구현
class SlackMessenger implements MessengerInterface {
public function send(string $message): bool {
// Slack API 호출 로직 구현
return true;
}
}
4-2. Email 메신저 전략
class MessengerFactory {
public static function create(string $type): MessengerInterface {
return match ($type) {
'slack' => new SlackMessenger(),
'email' => new EmailMessenger(),
default => throw new \InvalidArgumentException("Invalid messenger type"),
};
}
}
4-3. 전략을 활용하는 컨트롤러
class MessengerController {
public function handle(string $type, string $message): bool {
$messenger = MessengerFactory::create($type);
return $messenger->send($message);
}
}
4-4. 서비스 진입점
class NotificationService {
protected MessengerController $controller;
public function __construct(MessengerController $controller) {
$this->controller = $controller;
}
public function notify(string $type, string $message): bool {
return $this->controller->handle($type, $message);
}
}
4-6. 전략 패턴 흐름도 요약
- 클라이언트는 NotificationService에 메시지 전송 요청
- NotificationService는 MessengerController에 요청 전달
- MessengerController는 MessengerFactory를 통해 전략 객체(SlackMessenger, EmailMessenger 등) 생성
- 전략 객체의 send() 메서드 실행하여 메시지 전송
- 결과 반환 후, 최종적으로 클라이언트에게 응답 전달
5. 적용 시 이점
5-1. 기존 로직 변경 없이 신규 전략 추가 가능
- OCP(Open-Closed Principle)를 만족하여, 기존 코드를 건드리지 않고 새로운 전략을 쉽게 추가할 수 있습니다.
5-2. 의존성 주입(DI) 활용
- 컨테이너 바인딩을 통해 전략 객체를 주입하면, 테스트 시 모의 객체(Mock)를 사용하여 단위 테스트가 용이합니다.
5-3. 인터페이스 기반 테스트
- 각 전략은 인터페이스를 구현하므로, Mocking이나 Stub 객체를 활용해 독립적으로 테스트할 수 있습니다.
5-4. 비즈니스 로직과 구현 로직 분리
- 전략 패턴을 사용하면, 메시지 전송 방식과 실제 비즈니스 로직을 명확히 분리하여, 코드 가독성과 유지보수성이 향상됩니다.
6. 참고 자료
7. 사용 시 팁
7-1. 변경 가능성이 높은 알고리즘 또는 동작 영역을 인터페이스로 추상화
- 전략 패턴은 향후 변경될 가능성이 높은 알고리즘을 별도의 전략 객체로 분리하는 데 효과적입니다.
7-2. 인터페이스 기반 설계
- 모든 전략이 동일한 인터페이스를 구현하도록 하여, 클라이언트 코드에서 구체적인 구현에 의존하지 않도록 설계합니다.
7-3. 컨테이너 바인딩 활용
- Laravel의 서비스 컨테이너를 활용하여, 전략 객체를 자동으로 주입받는 방식으로 구성하면 DI 패턴을 극대화할 수 있습니다.
8. 공부 예정 항목
8-1. Laravel 서비스 프로바이더를 활용한 전략 주입 방식
- 서비스 프로바이더와 컨테이너 바인딩을 통해 전략 객체의 생성을 자동화하는 방법
8-2. 전략 패턴과 상태 패턴 비교
- 두 디자인 패턴의 차이점 및 적용 시 고려 사항 정리
8-3. 테스트 케이스 구조
- Mocking과 DI를 활용한 전략 패턴의 단위 테스트 작성 방법
'백엔드 > 디자인 패턴' 카테고리의 다른 글
[Laravel | PHP] 싱글톤 패턴 (0) | 2024.11.08 |
---|