전략 패턴이란?
객체의 특정 행동(알고리즘)을 직접 구현하지 않고, 외부에서 ‘전략’을 주입받아 갈아 끼우는 방식임
쉽게 말해 “본체는 그대로 두고, 부품만 바꿔서 기능을 바꾸는 것"이라 보면 됨
전략 패턴이 적용되지 않은 코드
전략 패턴을 쓰지 않으면 보통 이렇게 구현하게 됨
class Vehicle {
constructor(private type: "road" | "rail") {}
move() {
if (this.type === "road") {
console.log("부릉부릉 도로로 감 🚌");
} else if (this.type === "rail") {
console.log("칙칙폭폭 선로로 감 🚂");
}
}
}이 방식이 가지는 문제는 다음과 같음
조건문이 계속 늘어남 새로운 이동 방식이 생길 때마다 move()를 수정해야 함 → OCP(Open-Closed Principle) 위반
Vehicle 클래스가 알고리즘에 강하게 결합됨 → 이동 로직이 Vehicle 내부에 박혀 있음
유닛 테스트 어려움 Vehicle을 테스트하려면 항상 type 조건을 따라가야 함
코드 재사용성 낮음 “선로 전략”을 다른 곳에서 재사용할 수도 없고, 로직 분리가 안 됨
그러면 이 문제를 전략 패턴은 어떻게 해결할 수 있을까?
구조 설계
Vehicle(본체)은 MoveStrategy(부품)를 가지고 있고, 필요할 때 이 부품만 바꿈
classDiagram
class MoveStrategy {
<<interface>>
+move()
}
class RailStrategy {
+move()
}
class RoadStrategy {
+move()
}
class Vehicle {
-strategy: MoveStrategy
+setStrategy()
+move()
}
MoveStrategy <|.. RailStrategy
MoveStrategy <|.. RoadStrategy
Vehicle o-- MoveStrategyTypeScript 구현
1. 전략(Strategy) 정의
“어떻게 움직일지"에 대한 부품들임
// 행동의 규격 (인터페이스)
interface MoveStrategy {
move(): void;
}
// 부품 1: 도로용
class RoadStrategy implements MoveStrategy {
move() {
console.log("부릉부릉 도로로 감 🚌");
}
}
// 부품 2: 선로용
class RailStrategy implements MoveStrategy {
move() {
console.log("칙칙폭폭 선로로 감 🚂");
}
}2. 컨텍스트(Context) 정의
전략을 사용하는 본체임. setStrategy로 부품만 갈아 끼우면 됨
class Vehicle {
// 생성할 때 초기 전략(부품)을 낌
constructor(private strategy: MoveStrategy) {}
// 핵심: 실행 중에 부품 교체 가능!
setStrategy(strategy: MoveStrategy) {
this.strategy = strategy;
}
// 본체는 그냥 부품한테 일을 시킴 (위임)
move() {
this.strategy.move();
}
}3. 사용 예시
Vehicle 코드를 뜯어고칠 필요 없이, 주입하는 객체만 바꾸면 행동이 변함
// 1. 처음엔 도로 전략으로 생성
const bus = new Vehicle(new RoadStrategy());
bus.move(); // 결과: 부릉부릉 도로로 감 🚌
// 2. 갑자기 선로로 가야 함? 전략만 교체!
bus.setStrategy(new RailStrategy());
bus.move(); // 결과: 칙칙폭폭 선로로 감 🚂
핵심 요약
- 코드 수정 없음 (OCP): 새로운 이동 방식(예:
FlyStrategy)이 생겨도Vehicle클래스는 수정할 필요가 없음. 그냥 새 전략 만들어서 끼우면 됨 - 유연성: 실행 중(Runtime)에
setStrategy로 즉시 행동을 바꿀 수 있음 - 상속보단 합성: 복잡하게 클래스 상속(
extends) 하지 말고, 기능을 부품처럼 인터페이스로 받아서 쓰는 게 훨씬 유연함
참고자료
- https://en.wikipedia.org/wiki/Strategy_pattern
- https://refactoring.guru/design-patterns/strategy
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#compare-T-T-
- https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html
- https://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-