Waylog Blog

전략(Strategy) 패턴으로 알고리즘 교체하기

Design Pattern

게임을 만든다고 가정해 봅시다. 캐릭터의 무기가 '칼'에서 '활'로 바뀝니다. 이때마다 if (weapon == 'sword') attackWithSword() 처럼 조건문으로 분기 처리를 하면 코드가 지저분해지고 수정이 어렵습니다. 이럴 때 전략 패턴을 사용하면 실행 중에(Runtime) 알고리즘을 칩 갈아 끼우듯 교체할 수 있습니다.

1. 핵심 구조

  • Context: 전략을 사용하는 주체 (캐릭터)
  • Strategy Interface: 모든 전략이 구현해야 하는 공통 메서드 (attack())
  • Concrete Strategy: 실제 알고리즘 구현체 (칼, 활, 도끼)

2. 구현 예시

interface Weapon {
    void attack();
}

class Sword implements Weapon {
    public void attack() { System.out.println("칼로 벤다"); }
}

class Bow implements Weapon {
    public void attack() { System.out.println("활을 쏜다"); }
}

class Character {
    private Weapon weapon;
    
    public void setWeapon(Weapon w) { this.weapon = w; }
    
    public void fight() { weapon.attack(); }
}

이제 setWeapon(new Bow())만 호출하면 캐릭터의 공격 방식이 즉시 바뀝니다.

3. 상속보다 구성(Composition)

전략 패턴은 **"상속보다는 구성을 선호하라"**는 객체지향의 원칙을 가장 잘 보여줍니다. 부모 클래스의 메서드를 오버라이딩 하는 방식은 유연하지 못합니다. 행동을 별도의 클래스로 캡슐화하고 이를 조립(Composition)해서 사용하는 방식은 코드의 재사용성을 높여줍니다.

Spring Framework의 DiapatcherServlet이 핸들러 매핑 전략을 바꾸는 것, Passport.js가 인증 전략(Local, Google, Facebook)을 바꾸는 것도 다 이 패턴입니다.