본문 바로가기
iOS📱/Common

[디자인패턴] 커맨드 패턴 ( Command Pattern )

by 텅빈비니 2025. 2. 5.
반응형

안녕하세요🐶

빈지식 채우기의 비니🙋🏻‍♂️ 입니다.

 

오늘도 역시 학생과 선생님의 대화로 주제를 알아보도록 하겠습니다.

 

👨🏻‍💼 : 비니 학생, 혹시 MVVM 패턴에서 가장 중요한 요소에 대해 알고 있나요?

🙋🏻‍♂️ : 흠.. 의존성 해결? 모듈화 구성 가능? 유지보수 최적화? 인가요?

👨🏻‍💼 : 그것도 맞는 말이지만 커맨드 패턴 ( Command Pattern ) 라는 것을 사용하면 더 좋습니다. 오늘은 이것에 대해 알아보도록 하죠

🙋🏻‍♂️ : 넵!

 

넵! 오늘은 커맨드 패턴 ( Command Pattern ) 에 대해 알아보도록 하겠습니다.


1. 커맨드 패턴이란?

사용자가 보낸 요청을 객체의 형태로 캡슐화하는 패턴입니다.

 

이렇게 요청을 캡슐화 한다면,

어떤 작업에 대한 요청들을 객체로 만들어두고 필요에 따라서 객체에게 전달하는 방법으로 사용할 수 있습니다.

Command Pattern

  • Invoker : 요청을 보냄
  • Commanding : Command 의 인터페이스 ( 프로토콜 )
    • execute() : 요청을 처리한다.
    • unexecute() : 요청의 처리를 역으로 수행한다. ( Undo )
  • Command : 요청의 캡슐화
  • Receiver : 요청 객체을 통해 영향을 받음

2. 예시

일단 Invoker 와 Receiver 을 정의해보도록 하겠습니다.

  • Invoker : On(켜다) 를 수행할 객체 ( ex. 리모컨 )
  • Receiver : Invoker의 영향을 받을 객체 ( ex. TV )

어떠한 것의 수행될 동작은 On 으로 설정하도록 하겠습니다.

final class CommandPattern {
    private let onCommand: OnCommand	// 켜다의 동작 수행할 Command
    
    init(on: OnCommand) {
        self.onCommand = on
    }
    
    func on() {
        self.onCommand.execute()
    }
}

 

이렇게 구현할 수 있습니다.

 

우리는 커맨드 패턴을 사용하기 때문에,

직접적으로 Invoker(리모컨) 을 통해 Receiver(TV) 를 조작하지 않습니다.

Invoker(리모컨)가 가지게될 커맨드를 통해 Receiver(TV) 를 조작합니다.

 

커맨드 객체를 직접 소유하지 않고, 앞어 정리했던대로 인터페이스(프로토콜)을 소유하게 됩니다.

protocol Commanding {
    func execute()
    func unexecute()
}

 

그리고 On(켜다) 에 대한 객체를 Commanding 을 채택하는 객체로 구현하게 됩니다.

영향을 받을 Receiver(TV) 가 동작을 수행하려면 이 객체를 소유하고 있어야 합니다.

final class OnCommand: Commanding {
    let tv: String
    
    init(tv: String) {
        self.tv = tv
    }
    
    func execute() {
        // 실행될 코드
    }
    
    func unexecute() {
        // 돌아갈 코드
    }
}

 

이렇게 간단하게 커맨드 객체를 정의할 수 있습니다.

직접적으로 Invoker(리모컨) 이 Receiver(TV) 를 조종하기 않고 Command 를 통해 동작을 수행하도록 하게 합니다.

 

그럼 실제로 인스턴스를 생성하여 사용해보도록 하겠습니다.

let tv = TV()
let commandPattern = CommandPattern(
    on: OnCommand(tv: tv)
)
 
commandPattern.on()
 
//on
//Program ended with exit code: 0

 

이렇게 Receiver(TV) 객체를 생성한 뒤에 Command 인스턴스를 생성하여 Receiver(TV)를 주입합니다.

그리고 Command 패턴을 통해 Receiver(TV) 동작이 수행되도록 합니다.


3. 정리

이렇게 Command 패턴을 통해 MVVM에서 View 와 View Model 사이의 의존성을 해결할 수 있습니다.

  • Invoker : 이벤트를 날리는 View(ViewController)
  • Receiver : View Model
  • Command : ViewModel을 소유하고 특정한 이벤트를 캡슐화

위와 같이 구성된다면,

View 와 View Model 은 서로를 알지 못한 채로 이벤트를 전달할 수 있습니다.


감사합니다.


참고

반응형