728x90
반응형
새로운 기능이 추가될 때마다 늘어나는 if-else 문 때문에 코드를 읽기 어려웠던 적이 있으신가요? 기능이 바뀔 때마다 기존 코드를 수정해야 한다면 그것은 객체지향 설계의 신호등에 빨간불이 켜진 것입니다.
오늘은 동적으로 행동을 바꾸면서도 코드는 깔끔하게 유지할 수 있는 전략 패턴(Strategy Pattern)에 대해 깊이 있게 알아보겠습니다.

1. 전략 패턴이란?
전략 패턴은 특정 행동(알고리즘)을 직접 구현하지 않고, 개별적인 클래스로 캡슐화하여 상황에 따라 교체하며 사용할 수 있게 만드는 패턴입니다.
핵심 원칙
- 상속보다는 구성(Composition): 클래스를 상속받아 기능을 확장하는 대신, 인터페이스를 통해 전략을 '갈아 끼우는' 방식을 취합니다.
- OCP (개방-폐쇄 원칙): 기존의 Context 코드를 변경하지 않고도 새로운 전략을 무한히 추가할 수 있습니다.
2. 전략 패턴의 구조
이 패턴은 세 가지 핵심 요소로 구성됩니다.
- Strategy (인터페이스): 모든 전략 클래스가 구현해야 하는 공통의 인터페이스입니다.
- ConcreteStrategy (구체적인 전략): 실제로 동작하는 알고리즘을 구현한 클래스들입니다.
- Context (컨텍스트): 전략을 사용하는 주체입니다. 어떤 전략을 쓸지 결정하는 '전략 객체'를 가지고 있습니다.
3. Java 구현 예제: 다중 결제 시스템
사용자가 결제 시점에 신용카드, 카카오페이, 네이버페이 중 하나를 선택하는 상황을 구현해 보겠습니다.
Step 1. 전략 인터페이스와 구체적 전략
Java
// Strategy 인터페이스
interface PaymentStrategy {
void pay(int amount);
}
// 구체적인 전략 1: 신용카드
class CardPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 신용카드로 결제합니다.");
}
}
// 구체적인 전략 2: 카카오페이
class KakaoPayPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println(amount + "원을 카카오페이로 결제합니다.");
}
}
Step 2. Context 클래스 (쇼핑카트)
Java
class ShoppingCart {
private PaymentStrategy paymentStrategy;
// 실행 중에 전략을 설정(변경)할 수 있음
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void checkout(int amount) {
if (paymentStrategy == null) {
System.out.println("결제 수단을 선택해주세요.");
return;
}
paymentStrategy.pay(amount);
}
}
Step 3. 클라이언트 코드
Java
public class StrategyDemo {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 사용자가 신용카드를 선택한 경우
cart.setPaymentStrategy(new CardPayment());
cart.checkout(10000);
// 사용자가 결제 수단을 카카오페이로 변경한 경우
cart.setPaymentStrategy(new KakaoPayPayment());
cart.checkout(20000);
}
}
4. 전략 패턴의 장단점
👍 장점
- 런타임 유연성: 프로그램 실행 중에 알고리즘을 자유롭게 바꿀 수 있습니다.
- 코드 가독성: 복잡한 조건문(if-else)이 사라지고 로직이 명확해집니다.
- 테스트 용이성: 각 전략이 독립된 클래스이므로 단위 테스트가 매우 쉽습니다.
👎 단점
- 객체 수 증가: 전략이 많아질수록 관리해야 할 클래스 수도 늘어납니다.
- 사용자의 이해도: 클라이언트 코드가 어떤 전략들이 있는지 알고 있어야 적절한 선택이 가능합니다.
5. 실무 활용 및 꿀팁 (Java 8+)
최근 자바에서는 인터페이스의 메서드가 하나인 경우(Functional Interface), 굳이 클래스를 만들지 않고 람다식(Lambda)을 사용하여 더욱 간결하게 전략 패턴을 적용할 수 있습니다.
Java
// 클래스 생성 없이 즉석에서 전략 정의
cart.setPaymentStrategy(amount -> System.out.println(amount + "원 포인트 결제"));
결론
전략 패턴은 "변하는 것과 변하지 않는 것을 분리하라"는 객체지향의 대원칙을 가장 잘 보여주는 패턴입니다. 요구사항이 수시로 변하는 실무 환경에서 전략 패턴을 적절히 활용한다면, 유지보수가 즐거운 코드를 작성할 수 있을 것입니다.
포스팅이 도움이 되셨다면 공감과 구독 부탁드립니다! 여러분은 실무에서 어떤 if 문을 전략 패턴으로 바꾸고 싶으신가요? 댓글로 공유해 주세요!
반응형
'Mobile & App Stack > Java Software Architecture & Patterns' 카테고리의 다른 글
| 커맨드 패턴 완벽 정리: Undo/Redo 기능을 만드는 가장 스마트한 방법 (0) | 2025.01.02 |
|---|---|
| 옵저버 패턴(Observer) 완벽 정리: Java 예제와 Deprecated 대안 (0) | 2025.01.01 |
| 플라이웨이트 패턴 완벽 정리: 메모리 사용량을 90% 줄이는 마법 (0) | 2024.12.29 |
| 브리지 패턴(Bridge Pattern) 완벽 정리: 클래스 폭발을 막는 설계의 기술 (0) | 2024.12.28 |
| 퍼사드 패턴(Facade Pattern) 완벽 정리: 복잡한 시스템을 단순하게 만드는 마법 (0) | 2024.12.27 |