
Unity에서 커맨드 패턴 (Command Pattern) 이해하기
커맨드 패턴은 객체 지향 프로그래밍의 디자인 패턴 중 하나로, 명령을 하나의 객체로 캡슐화하여 호출자와 수신자의 결합도를 낮추고 코드의 유연성과 확장성을 높입니다. 특히 게임 개발에서 자주 사용되며, 다양한 입력 처리를 효율적으로 관리할 수 있습니다.
커맨드 패턴의 개념
커맨드 패턴은 명령을 객체 형태로 캡슐화하여 호출자(Invoker)와 수신자(Receiver) 간의 결합도를 낮춥니다. 이를 통해 명령을 큐(queue)나 스택(stack)에 저장하여 나중에 실행하거나 취소(undo), 재실행(redo)할 수 있습니다. 예를 들어, 전략 게임에서 유닛의 이동 명령을 큐에 저장하고, 자원에 따라 순차적으로 실행할 수 있습니다. 이를 통해 각 명령을 독립적으로 관리하고, 명령을 쉽게 추가하거나 수정할 수 있습니다.
주요 구성 요소
- 커맨드 인터페이스 (Command Interface):
- 모든 커맨드 객체가 구현해야 하는 메서드를 정의합니다. 주로 Execute()와 Undo() 메서드를 포함합니다.
- 구체적인 커맨드 클래스 (Concrete Command Class):
- Command 인터페이스를 구현하며, 실제 수행할 명령을 정의합니다.
- 리시버 (Receiver):
- 실제 명령을 수행하는 객체입니다. 예를 들어, Light 클래스는 불을 켜고 끄는 기능을 가집니다.
- 인보커 (Invoker):
- 클라이언트가 명령을 요청하는 역할을 합니다. 인보커는 커맨드 객체를 받아서 Execute() 메서드를 호출합니다.
- 클라이언트 (Client):
- 인보커에게 어떤 명령을 수행할지 설정합니다.
예제: Unity에서 커맨드 패턴 구현하기
다음은 Unity에서 커맨드 패턴을 사용하여 캐릭터를 이동시키고, undo/redo 기능을 구현하는 예제입니다.
- 커맨드 인터페이스 정의
public interface ICommand
{
void Execute();
void Undo();
}
- 구체적인 커맨드 클래스 정의
public class MoveCommand : ICommand
{
private Transform _characterTransform;
private Vector3 _direction;
public MoveCommand(Transform characterTransform, Vector3 direction)
{
_characterTransform = characterTransform;
_direction = direction;
}
public void Execute()
{
_characterTransform.position += _direction;
}
public void Undo()
{
_characterTransform.position -= _direction;
}
}
- 리시버 클래스 정의
public class CharacterMover : MonoBehaviour
{
public Transform characterTransform;
public void Move(Vector3 direction)
{
characterTransform.position += direction;
}
public void UndoMove(Vector3 direction)
{
characterTransform.position -= direction;
}
}
- 인보커 클래스 정의
public class InputHandler : MonoBehaviour
{
public Transform characterTransform;
private Stack<ICommand> _commandHistory = new Stack<ICommand>();
void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
ExecuteCommand(new MoveCommand(characterTransform, Vector3.forward));
}
if (Input.GetKeyDown(KeyCode.S))
{
ExecuteCommand(new MoveCommand(characterTransform, Vector3.back));
}
if (Input.GetKeyDown(KeyCode.A))
{
ExecuteCommand(new MoveCommand(characterTransform, Vector3.left));
}
if (Input.GetKeyDown(KeyCode.D))
{
ExecuteCommand(new MoveCommand(characterTransform, Vector3.right));
}
if (Input.GetKeyDown(KeyCode.Z) && _commandHistory.Count > 0)
{
UndoCommand();
}
}
void ExecuteCommand(ICommand command)
{
command.Execute();
_commandHistory.Push(command);
}
void UndoCommand()
{
ICommand command = _commandHistory.Pop();
command.Undo();
}
}
이 예제에서는 InputHandler 클래스가 인보커 역할을 하며, MoveCommand 객체를 생성하고 실행합니다. 실행된 명령은 스택에 저장되어 나중에 취소할 수 있습니다.
커맨드 패턴의 장점과 단점
장점:
- 단일 책임 원칙 준수: 각 커맨드 객체는 하나의 명령만 처리하여 단일 책임 원칙(Single Responsibility Principle)을 지킵니다.
- 유연성과 확장성: 새로운 명령을 추가할 때 기존 코드를 수정할 필요 없이 확장할 수 있습니다.
- 명령 저장 및 관리: 명령을 큐나 스택에 저장하여 나중에 실행하거나 취소할 수 있습니다.
- 저결합성: 호출자와 수신자 간의 결합도를 낮춰 코드의 유연성과 재사용성을 높입니다.
단점:
- 클래스 수 증가: 각 명령마다 클래스를 생성해야 하므로 클래스 수가 증가하여 복잡성이 높아질 수 있습니다.
- 오버헤드: 명령을 관리하는 추가적인 오버헤드가 발생할 수 있습니다.
결론
커맨드 패턴은 게임 개발에서 다양한 입력 처리를 효율적으로 관리하고 복잡한 기능을 간단하게 구현할 수 있는 강력한 도구입니다. 이 패턴을 활용하면 코드의 가독성을 높이고, 유지보수와 확장이 쉬운 유연한 구조를 만들 수 있습니다. 특히 전략 게임이나 퍼즐 게임처럼 복잡한 입력과 명령 관리가 필요한 경우에 매우 유용합니다. 커맨드 패턴을 통해 명령을 독립적으로 관리하고 쉽게 추가하거나 수정할 수 있어, 개발 과정에서의 생산성을 크게 향상시킬 수 있습니다. 이러한 장점들은 코드의 품질을 높이고, 프로젝트의 성공 가능성을 증가시키는 중요한 요소가 됩니다.
'Unity > 디자인 패턴' 카테고리의 다른 글
| [Unity] MVP(Model-View-Presenter) 패턴 이해 및 활용 (0) | 2025.06.03 |
|---|---|
| [Unity] MVC(Model-View-Controller) 패턴 이해 및 활용 (0) | 2025.06.03 |
| [Unity] 디자인 패턴 - 옵저버(Observer) 패턴 이해하기 (0) | 2025.06.03 |
| [Unity] 디자인 패턴 - 상태(State) 패턴 이해하기 (0) | 2025.06.03 |
| [Unity] 디자인 패턴 - 싱글톤(Singleton) 패턴 이해하기 (0) | 2025.06.03 |