커맨드 패턴 가이드: 요청을 객체로 다루면 뭐가 좋아질까
Dev

커맨드 패턴 가이드: 요청을 객체로 다루면 뭐가 좋아질까


프로그램에서 “무엇을 실행할 것인가”를 다루다 보면, 단순 함수 호출로는 부족해지는 순간이 있습니다. 요청을 나중에 실행해야 하거나, 큐에 넣어야 하거나, 이력으로 남겨야 하거나, 취소/재실행을 다루고 싶을 때가 그렇습니다. 커맨드 패턴은 이런 문제를 설명할 때 자주 등장하는 패턴입니다.

이 글에서는 아래 내용을 정리합니다.

  • 커맨드 패턴이 무엇인지
  • 왜 요청을 객체로 감싸는지
  • 어떤 상황에서 유용한지
  • 큐잉, 재실행, 취소와 어떻게 연결되는지

핵심은 커맨드 패턴은 실행할 요청을 객체로 표현해서, 실행 시점과 실행 주체를 더 유연하게 다룰 수 있게 만드는 구조라는 점입니다.

커맨드 패턴이란 무엇인가

커맨드 패턴은 “실행할 작업”을 하나의 객체로 다루는 방식입니다.

즉:

  • 무엇을 할지
  • 어떤 데이터로 할지

를 객체 안에 담아두고, 나중에 실행할 수 있게 합니다.

왜 유용할까

요청을 그냥 즉시 함수로 실행하면:

  • 나중에 실행하기 어렵고
  • 큐에 넣기 어렵고
  • 이력 관리가 어렵고
  • 공통 처리 로직을 얹기 어렵습니다

반대로 요청을 객체로 만들면 실행을 데이터처럼 다룰 수 있습니다.

어떤 상황에서 잘 맞을까

  • 버튼 클릭 액션
  • 작업 큐
  • undo/redo
  • 배치 실행
  • 실행 이력 저장

즉, “요청” 자체를 독립적인 단위로 다뤄야 할 때 특히 잘 맞습니다.

큐잉과는 왜 잘 어울릴까

커맨드 객체는 실행해야 할 정보가 묶여 있으므로:

  • 큐에 넣고
  • 나중에 꺼내서 실행하고
  • 실패 시 재시도하고

같은 흐름과 잘 어울립니다.

그래서 백그라운드 작업이나 비동기 처리 구조를 설명할 때도 자주 연결됩니다.

자주 하는 오해

1. 함수가 있는데 왜 굳이 객체로 감싸나

즉시 실행만 필요한 코드라면 과할 수 있지만, 실행을 저장하고 전달해야 하면 꽤 큰 차이가 납니다.

2. 커맨드 패턴은 UI 코드에서만 쓴다

작업 큐, 배치, 자동화 흐름에서도 충분히 잘 맞습니다.

3. 모든 액션은 커맨드 패턴으로 만들어야 한다

항상 그럴 필요는 없습니다. 요청을 독립 단위로 다뤄야 하는 상황에서 특히 가치가 큽니다.

Simple Example

interface Command {
	execute(): void;
}

class SendEmailCommand implements Command {
	constructor(private email: string) {}

	execute(): void {
		console.log(`Send email to ${this.email}`);
	}
}

class CommandQueue {
	private commands: Command[] = [];

	add(command: Command): void {
		this.commands.push(command);
	}

	run(): void {
		this.commands.forEach((command) => command.execute());
	}
}

const queue = new CommandQueue();
queue.add(new SendEmailCommand('team@example.com'));
queue.run();

The request is turned into an object, so we can queue it, delay it, log it, or swap the executor later.

FAQ

Q. 입문자는 어디서 커맨드 패턴을 떠올리면 좋을까

나중에 실행, 반복 실행, 취소, 큐잉 같은 요구가 보일 때 떠올리기 좋습니다.

Q. 전략 패턴과는 어떻게 다른가

전략은 행동 방식 교체, 커맨드는 실행 요청 자체를 객체화하는 데 더 가깝습니다.

Q. 커맨드 패턴은 이벤트와 같은가

비슷하게 느껴질 수 있지만, 커맨드는 실행 가능한 요청 단위라는 점에 더 초점이 있습니다.

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.