회사에서 컴포넌트를 리팩토링하는 작업을 맡게 되었다. 이 컴포넌트는 드롭다운을 열거나 닫고, 투파트 버튼을 눌러 특정 동작을 실행하는 등 다양한 UI 액션을 담당하고 있었으며, 모든 동작은 외부에서 주입받은 "커맨드 객체"를 통해 이루어지는 구조였다.
처음 코드를 봤을 때는 이해조차 어려웠었다. 라인수도 많기도 했지만 처음 보는 구조였기에 이해하는데 고생을 했던 기억이 있다. 그래도 이번 업무를 진행하며 커맨드 버튼이 어느 시점에서 사용되는지 어떤 방법으로 구현되는지 조금은 알 것 같다.
커맨드 패턴이란?
커맨드 패턴(Command Pattern) 은 요청(명령) 을 하나의 객체(Command 객체) 로 캡슐화해서, 실행자(Invoker)와 수신자(Receiver)를 분리하는 디자인 패턴이다.
즉, “무엇을 실행할지”와 “어떻게 실행할지”를 분리해주는 구조
그러면 커맨드 패턴을 왜 써야하는지 부터 생각해보자. 우선 가장 큰 문제점은 요청을 실행하는 실행부와, 처리하는 부분이 강하게 결합되어있다는 점이다.
예를들어 어떤 버튼 컴포넌트를 만들었다고 가정하자. 그 버튼은 엄청나게 많은 기능을 가질 수 있으며, 상황에 따라 ctrl + z 와 같은 undo 기능이 있어야 한다.
왜 커맨드 패턴을 사용해야하는가?
내가 지금까지 했던 방식은 버튼은 이벤트를 받을 수 있도록 설계하고, 그 이벤트가 발생하는 시점에 함수를 구현했었다. 그렇다면 ToolHolder 라는 컴포넌트에 다음과 같은 양의 이벤트가 필요하다고 가정한다면 이 모든 이벤트를 툴 바에서 구현해야한다.

적어도 10가지가 넘는 핸들러를 하나의 컴포넌트 내에서 선언해야하고, 이 명령들은 컴포넌트 레이어에 존재한다. 그럼 클라이언트 레이어에서는 해당 기능을 "반드시" 가지고 있어야 한다. 이 부분에서 첫 번째 문제점이 발생한다. 클라이언트에서는 해당 명령들을 가질 필요도 없으며 가져서도 안된다.
만약 어떤 기능이 바뀌어야 한다면? 컴포넌트 단에서 툴바 컴포넌트의 명령을 바꾸면 된다. 그럼 그에 따른 사이드 이펙트는 고스란히 클라이언트 단으로 올라온다.
두 번째는 undo와 redo와 같은 기능을 구현하기 매우 쉽다. 명령을 분리했으니 관리하기도 한결 편해진다. 명령끼리 모아놨으니 여러 명령을 순차적으로 실행하는 로직을 만들 수도 있고, 큐에 담아서 명령을 undo, redo 혹은 사용자 이벤트의 로깅도 남길 수 있다.
사실 나도 완벽하게 커맨드 패턴을 이해 한 것 같지는 않다. 단순히 "명령을 모아 두고 사용한다" 정도는 알겠는데 그에 따른 여러 사용성이 어떤 것 들이 있을지는 직접 겪어보기 전까지는 잘 모르겠다.
뭔가 부족한 것 같지만 아무튼 뭐 거의 두달만에 블로그 쓰기 완!
'개발' 카테고리의 다른 글
| [디자인 패턴] 디자인 패턴 시작 (7) | 2025.06.08 |
|---|