전략 패턴(Strategy Pattern)

김세빈·2025년 4월 28일

CS

목록 보기
13/22

전략 패턴(Strategy Pattern) 이해하기

전략 패턴(Strategy Pattern)은 "전략"이라고 부르는 알고리즘을 캡슐화하여,
컨텍스트(Context) 안에서 서로 교체할 수 있게 만드는 디자인 패턴입니다.

즉, 하나의 기능(예: 로그인, 결제 등)을 다양한 방법으로 구현할 수 있고,
이 방법들을 쉽게 갈아끼울 수 있도록 설계합니다.


전략 패턴을 적용하는 이유

전략 패턴을 적용하면 다음과 같은 장점이 있습니다.

  • 확장성: 새로운 전략을 추가해도 기존 코드를 수정할 필요가 없습니다.
  • 유연성: 실행 중에도 전략을 자유롭게 교체할 수 있습니다.
  • 캡슐화: 구체적인 전략의 내부 구현을 숨길 수 있습니다.

실생활에서 보는 전략 패턴

예를 들어, 사용자가 로그인할 때 다음과 같은 전략을 선택할 수 있습니다.

  • 카카오 로그인
  • 구글 로그인
  • 애플 로그인

또는 결제할 때 다음과 같은 전략을 사용할 수 있습니다.

  • 신용카드 결제
  • 카카오페이 결제
  • 페이팔 결제

Node.js의 유명한 인증 라이브러리인 passport도 전략 패턴을 기반으로 설계되어 있습니다.
여러 인증 전략(passport-kakao, passport-google 등)을 쉽게 추가하고 교체할 수 있습니다.


Java 코드로 전략 패턴 구현하기

아래는 쇼핑몰 결제 시스템을 전략 패턴으로 구현한 예시입니다.

1. 전략(Strategy) 인터페이스 정의

interface PaymentStrategy {
    void pay(int amount);
}

2. 구체적인 전략(Concrete Strategy) 구현

class KakaoCardStrategy implements PaymentStrategy {
    private final String name;
    private final String cardNumber;
    private final String cvv;
    private final String dateOfExpiry;

    public KakaoCardStrategy(String name, String cardNumber, String cvv, String dateOfExpiry) {
        this.name = name;
        this.cardNumber = cardNumber;
        this.cvv = cvv;
        this.dateOfExpiry = dateOfExpiry;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + "원을 KakaoCard로 결제합니다.");
    }
}

class LunaCardStrategy implements PaymentStrategy {
    private final String emailId;
    private final String password;

    public LunaCardStrategy(String emailId, String password) {
        this.emailId = emailId;
        this.password = password;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + "원을 LunaCard로 결제합니다.");
    }
}

3. Context 역할을 하는 ShoppingCart 클래스

import java.util.ArrayList;
import java.util.List;

class Item {
    private final String name;
    private final int price;

    public Item(String name, int cost) {
        this.name = name;
        this.price = cost;
    }

    public int getPrice() {
        return price;
    }
}

class ShoppingCart {
    private final List<Item> items = new ArrayList<>();

    public void addItem(Item item) {
        items.add(item);
    }

    public void removeItem(Item item) {
        items.remove(item);
    }

    public int calculateTotal() {
        return items.stream().mapToInt(Item::getPrice).sum();
    }

    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}

4. 사용 예시

public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("노트북", 2000000);
        Item item2 = new Item("마우스", 50000);

        cart.addItem(item1);
        cart.addItem(item2);

        // KakaoCard로 결제
        PaymentStrategy kakaoPay = new KakaoCardStrategy("홍길동", "1234-5678-9012-3456", "123", "12/25");
        cart.pay(kakaoPay);

        // LunaCard로 결제
        PaymentStrategy lunaPay = new LunaCardStrategy("user@example.com", "securepassword");
        cart.pay(lunaPay);
    }
}

실행 결과

2050000원을 KakaoCard로 결제합니다.
2050000원을 LunaCard로 결제합니다.

정리

  • 전략 패턴은 실행 알고리즘을 캡슐화하고, 쉽게 교체할 수 있도록 설계합니다.
  • 컨텍스트(ShoppingCart)는 구체적인 전략(PaymentStrategy의 구현체)을 몰라도 됩니다.
  • 덕분에 확장성유지보수성이 크게 향상됩니다.

마무리

디자인 패턴을 공부하다 보면 "왜 이렇게 복잡하게 만들지?"라고 생각할 때가 있습니다.
하지만 실제 서비스가 커지고 기능이 추가될수록,
전략 패턴 같은 유연한 설계가 얼마나 중요한지 몸소 느끼게 됩니다.

기억해야 할 핵심은 다음과 같습니다:

"변화에 유연하게 대응할 수 있도록 미리 준비하는 것"
그게 바로 좋은 설계입니다.

0개의 댓글