DevDino

[게임 디자인 패턴] 전략 패턴(Strategy Pattern) 본문

Unity/디자인 패턴

[게임 디자인 패턴] 전략 패턴(Strategy Pattern)

데브다이노 2026. 7. 14. 14:50

Strategy Pattern

게임을 개발하다 보면 캐릭터의 행동 방식(알고리즘)을 상황에 따라 다르게 적용해야 할 때가 있습니다. 

메서드 안에서 조건문으로 구분하여 구현할 수는 있지만, 방식이 늘어날수록 코드는 꼬이게 됩니다.

 

이런 복잡한 분기문에서 벗어나 행동 방식(알고리즘)을 부품처럼 갈아 끼울 수 있게 만들어주는 전략 패턴에 대해 알아보겠습니다.

 

전략 패턴(Strategy Pattern)이란?

전략 패턴은 일련의 알고리즘을 정의하고 각각을 캡슐화하여, 이들을 상호 교체 가능하게 만드는 디자인 패턴입니다. 이 패턴의 주요 목적은 런타임에 어떤 동작을 사용할 것인지에 대한 결정을 연기하는 데 있습니다. 행동 방식 자체를 개별 전략 클래스로 분리해 캡슐화함으로써, 상황에 맞춰 실행 중에 동적으로 알고리즘을 선택하고 적용할 수 있습니다. 

전략 패턴의 장점

- 코드의 가독성 향상: 조건문이 사라져 코드가 훨씬 깔끔해집니다. 

- 유지보수 및 확장성 증가: 새로운 방식을 추가할 때 기존 코드를 수정할 필요 없이 새로운 전략 클래스만 추가하면 됩니다(개방-폐쇄 원칙 준수).

- 런타임 교체 가능: 게임 실행 도중(예: 아이템 스왑)에 캐릭터의 행동 방식을 즉각적으로 교체할 수 있습니다. 

 

구현 예제

전략 패턴을 유니티에 적용하기 위해 크게 3가지 요소가 필요합니다. 

1. IStrategy(인터페이스): 모든 전략이 공통으로 가질 메서드를 정의합니다. 

2. Context(전략 사용자): 현재 사용할 전략을 가지고 있으며, 필요할 때 전략을 교체합니다. 

3. Concrete Strategies(구체적인 전략들): IStrategy를 상속받아 실제로 동작을 구현하는 클래스들입니다. 

 

1. IStrategy 인터페이스 정의하기

먼저 모든 전략 클래스가 지켜야 할 규칙을 만듭니다. 공격 행동을 전략으로 분리해 보겠습니다. 

public interface IAttackStrategy
{
    void Attack();
}

 

2. 구체적인 전략 클래스 만들기

IAttackStrategy 인터페이스를 상속받아 실제 행동 방식들을 구현합니다. 

using UnityEngine;

public class MeleeAttackStrategy : IAttackStrategy
{
    public void Attack()
    {
        Debug.Log("근접 공격");
    }
}
using UnityEngine;

public class RangeAttackStrategy : IAttackStrategy
{
    public void Attack()
    {
        Debug.Log("원거리 공격");
    }
}

 

3. 전략 사용자(Context) 만들기

마지막으로 이 전략들을 장착하고 실행해 줄 MonoBehaviour 스크립트가 필요합니다. 유니티 프로젝트에서 실제 캐릭터에 부착될 클래스입니다. 

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // 현재 장착된 전략(행동 방식)
    private IAttackStrategy currentAttackStrategy;
    
    void Start()
    {
        // 게임이 시작되면 기본 무기(전략)를 근접 공격으로 설정합니다. 
        SetAttackStrategy(new MeleeAttackStrategy());
    }
    
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            PerformAttack();
        }

        // 숫자키 1, 2번을 눌러 런타임에 무기(전략)를 교체합니다.
        if (Input.GetKeyDown(KeyCode.Alpha1))
            SetAttackStrategy(new MeleeAttackStrategy());
            
        if (Input.GetKeyDown(KeyCode.Alpha2))
            SetAttackStrategy(new RangeAttackStrategy());
    }
    
    // 전략을 교체하는 핵심 메서드입니다. 
    public void SetAttackStrategy(IAttackStrategy newStrategy)
    {
        currentAttackStrategy = newStrategy;
    }
    
    // 현재 장착된 전략의 메서드를 실행합니다.
    public void PerformAttack()
    {
        if (currentAttackStrategy != null)
        {
            currentAttackStrategy.Attack();
        }
    }
}

 

코드를 보면 PlayerController 클래스의 Update 문 안에는 무기(전략)를 구분하는 조건문이 없습니다. 그저 현재 장착된 전략에게 실행을 위임하고 있을 뿐입니다.

 

처음 전략 패턴을 적용할 때는 클래스 파일이 많아져서 번거롭게 느껴질 수 있으나, 상황에 따라 패턴이 달라지는 시스템을 개발할 때 프로젝트의 확장성을 크게 높여줍니다. 

 

참고: 전략 패턴과 상태 패턴의 핵심 차이
두 패턴은 클래스 구조가 거의 같지만, 사용 목적과 변화의 주체가 다릅니다.

- 전략 패턴: 어떻게(How) 할 것인가?
목적을 달성하기 위한 방법(알고리즘)을 외부(클라이언트)에서 선택하여 주입합니다. 
예) 결제 시스템에서 신용카드 결제, 계좌 이체, 간편 결제 중 사용자가 원하는 결제 방식을 선택해서 갈아 끼우기

- 상태 패턴: 어떤 상태(What)인가?
객체의 내부 상태에 따라 행동이 달라지며, 조건에 따라 스스로 다음 상태로 전환합니다. 
예) 비디오 플레이어에서 재생/일시정지 버튼을 누르면 현재 상태에 따라 재생 또는 일시정지 상태로 전환