jtwjs Dev Wiki
  • DEV_ROAD
    • 💪🏻 생존하기
    • Week 1
      • 개발 환경 세팅
      • 타입스크립트
      • 리엑트
      • Testing Library
      • Parcel & ESLint
    • Week 2
      • JSX
      • Virtual DOM
    • Week 3
      • React Component
      • React State
    • Week 4
      • Express
      • Fetch API & CORS
      • React Hook
      • useRef & Custom Hook
    • Week 5
      • TDD
      • React Testing Library
      • MSW
      • Playwrite
      • Snapshot
    • Week 6
      • Separtion of Concerns
      • Principle
      • DI, (Dependency Injection)
      • Reflect-metadata
      • TSyringe
      • External Store
      • Follow Redux
      • usestore-ts
      • useSyncExternalStore
    • Week 7
      • Routing
      • Routes
      • Router
      • Navigation
    • Week 8
      • Design System
      • Style Basics
      • CSS-in-JS
      • Styled-Components
      • Global Style & Theme
    • Week 9
      • 개발하기 전 준비
      • 상품 목록 페이지
      • 상품 상세 페이지
      • 장바구니 페이지
    • Week 10
      • 로그인
      • 로그아웃
      • 회원가입
      • 주문 목록 & 주문 상세
    • Week 11
      • 배송 정보 입력
      • 포트원 결제 요청
      • 배송 및 결제 정보 전달
    • Week 12
      • 관리자 웹사이트개발시작
  • DEV_NOTE
    • TypeScript
      • 기본적 문법
        • Enum
        • 다형성
          • Untitled
        • 구조적 타이핑
        • 제너릭 타입
        • 컨디셔널 타입
        • 함수 메서드 타이핑
        • infer로 타입스크립트의 추론 직접 활용
        • 재귀 타입
        • 템플릿 리터럴 타입
        • 추가적인 타입 검사 satisfies 연산자
        • 타입스크립트 건망증
        • 원시 자료형에도 브랜딩 기법 사용 가능
        • 타입 좁히기
        • 유용한 타입 만들기
        • 데코레이터 함수
        • 앰비언트 선언도 선언 병합이 된다.
        • 앰비언트 선언도 선언병합이 된다.
    • Testing
      • Unit Testing
      • 단위 테스트의 두 분파
      • 좋은 단위 테스트를 구성하는 4대 요소
      • 테스트 대역과 식별할 수 있는 동작
      • 단위 테스트 스타일
      • 가치 있는 단위 테스트를 위한 리팩토링
      • 통합 테스트
      • Cross Browsing Testing
      • 기능 테스트 종류
      • React Testing Pattern
      • 프론트엔드 테스트 입문
        • 테스트 범위
        • 단위 테스트 검증
        • Mock
        • UI 컴포넌트 테스트
        • 테스트 커버리지
        • 웹 통합 테스트
        • MSW
        • 스토리북
        • 시각적 회귀 테스트
        • E2E 테스트
        • Github Actions 설정
        • 깃허브 액션에서 E2E
      • 시프트 레프트
        • 테스트 기본중의 기본
        • 단위 테스트
        • 코드 복잡도
        • 리팩터링
        • 코드 리뷰
        • 통합 테스트 패턴
        • 시스템 테스트의 자동화
        • 탐색적 테스트
      • Test Tip
      • vitest
      • playwright
      • Test Data Generator
      • MSW
    • Algorithm
      • coding test
      • Data Structure
    • Next.js
      • Data Fetching
      • Hydration
      • Next 13
      • Optimization
      • Next 15
        • ETC.
    • Tailwind
      • Tailwind CSS
      • Theme
      • Directives
      • Tool
      • Design System
      • Shadcn UI
    • Storybook
      • Storybook
      • CSF3
      • CDD
      • Headless Component
    • Funtional Programming
      • 함수형 프로그래밍
      • 참조 투명성
      • 부수효과
      • 함수 합성
      • 제너릭 타입 활용하기
      • 암묵적 입출력
      • 액션과 계산, 데이터
      • 계층형 설계
      • 호출 그래프
      • 함수형 설계
      • 불변성
      • 일급 함수
      • 함수형 도구
    • Git
      • Github Actions
      • Conflict
      • Branch 전략
    • Contents Format
      • Audio
    • 3D Graphic
      • 3D keyword
      • Three.js
      • Geometry
      • Material
      • Light
      • Camera
      • Decal
      • Rotation
      • Text
      • Shadow
      • Fog
      • Post Processing
      • Animation
      • Math
        • Vector Space
        • 벡터의 연산
        • 회전 계산
      • 3D 컨텐츠가 만들어지는 과정
      • R3F
      • Env
      • Scene
      • Transform
      • R3F
      • Interaction & Raycast
      • Rendering Algorithnm
      • Blender
    • Accessibility
      • 접근성이란
    • Interactive Web
      • Parallax
      • Canvas
      • requestAnimationFrame
      • Effect
      • HSL
      • React.js + Canvas
      • Matter.js
    • AWS
      • DevOps
      • Amplify
      • S3
      • 클라우드 컴퓨팅
        • 온프레미스와 클라우드
        • 클라우드 도입효과
        • 클라우드 컴퓨팅의 범위
        • 컴퓨팅 옵션
          • EC2 - Virtual Machin
          • ECS, EKS - Container
          • Lambda - Serverless
        • 네트워크 가상화
        • 스토리지
        • 데이터베이스
        • 데이터 수집
        • 머신 러닝 영역
        • IoT 영역
        • 블록체인 영역
      • 클라우드 아키텍처 설계
    • Network
      • Web Server & WAS
    • System Design
      • System Design
      • Component
      • 의존성을 배제한 개발
      • Error Handling
      • Architecture
        • 모노로틱 아키텍처
        • Clean Architecture
        • Layered Architecture
        • 이벤트 기반 아키텍처
      • 상황을 파악하는 메타인지
      • 중복 문제 해결하기
      • Monorepo Arhitecture
        • 모노레포 운영과 트러블슈팅
        • Module Federation
      • 코드 병목지점
      • API 대응
      • 공통 코드
      • Infra 구축
      • 모듈 기반의 개발 방식
      • Design System
        • 최소 수준의 아키텍처 설정
        • 더 효율적인 디자인시스템 만들기
        • 디자인 시스템과 UI 라이브러리 목적
        • 디자인 토큰
      • 효율적인 업무
        • 업무 프로세스 병목 파악
      • Clean Code
      • Design Pattern
        • CQRS Pattern
        • Strangler Fig Pattern
        • 데코레이터 패턴
        • 커맨드 패턴
        • 전략 패턴
        • 옵저버 패턴
      • A/B 테스팅
      • 대규모 리엑트 웹앱 개발
        • 복잡성 관리
        • 모듈성
        • 성능
        • 디자인 시스템
        • 데이터 패칭
        • 상태 관리
        • 국제화
        • 코드 조직화하기
        • 개인화 A/B 테스팅
        • 확장 가능한 웹 아키텍처
        • 테스팅
        • 툴링
        • 기술적 마이그레이션
        • 타입스크립트
        • 라우팅
        • 사용자 중심 API 디자인
        • 리액트 미래
    • Performance
      • React DevTools
      • Component 최적화
      • Page Load
      • API
    • MFA
      • MSA
      • MFA 도입하기
      • Monorepo
        • Monorepo Tool
        • Yarn Berry Workspace
        • Turborepo
      • MFA Composition
      • SPA 통합
      • Design System
      • Package Manager
        • Yarn
        • pnpm
      • Transpiler & Bundler
        • Babel
        • Rollup
        • esbuild
        • swc
        • Webpack
        • Vite
      • 분해와 통합을 위한 여러 기술 비교
    • State Management
      • Zustand
    • React v18
      • Automatic batching
      • Suspense
      • Transition
    • SEO
      • Search Engine Optimization
      • Open Graph Element
      • Metadata
    • FE Develop
      • User Scenario
      • Optimization
      • Browser API
        • Scrubbing
        • Clipboard
      • Folder Structure
      • API First Design
      • 통합 테스트
      • 테크 스펙
      • 이슈 관리 with Jira
    • Refactoring
      • 리팩토링 깊게 들여다보기
      • 긴 코드 조각내기
      • 타입 코드 처리하기
      • 유사한 코드 융합하기
      • 데이터 보호
      • 코드 추가 및 제거
    • OAuth 2.0
    • Analytics
      • Mixpanel
    • ETC
      • VSCode
    • React Hook In Action
      • useContext & Provider
      • 커스텀 훅
      • 코드 분할하기 with Suspense, lazy
      • Suspense와 이미지 적재하기
      • useTransition, uesDeferredValue
      • SuspenseList
    • AI
      • Cursor
    • UI library
      • vanila-extract
      • Headless
      • 테스트 코드
      • 문서화
Powered by GitBook
On this page
  • 커맨드 패턴
  • 키워드
  • 핵심 정리
  • 커맨드 객체 만들기
  • NoCommand 객체
  • 작업 취소 기능 추가하기
  • 여러 동작을 한 번에 처리하기
  1. DEV_NOTE
  2. System Design
  3. Design Pattern

커맨드 패턴

커맨드 패턴

요청 내역을 객체로 캡슐화해서 객체를 서로 다른 요청 내역에 따라 매개변수화할 수 있다.

이러면 요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용할 수 있다.

  • 명령을 추상화해서 객체로 사용한다.

  • 클라이언트에서 커맨드 객체 생성

    • 커맨드 객체에는 행동과 리시버(receiver)의 정보가 같이 들어있음

    • 커맨드 객체에서 제공하는 메소드는 excute() 하나뿐

      • 행동을 캡슐화하며 리시버에 있는 특정 행동을 처리한다.

  • 인보커(invoker) 객체의 setCommand() 메서드에 커맨드 객체를 넘겨서 호출

    • 넘긴 커맨드객체를 사용하기 전까지 인보커 객체에서 보관

    • ex: remoteControl.setCommand(0, partyOnMacro, partyOffMacro)

  • 인보커에서 커맨드 객체의 excute() 메서드 호출

    • 리시버에 있는 행동 메서드가 호출됨

키워드

  • 인보커(Invoker): 명령이 들어있으며, execute() 메서드를 호출함으로써 커맨드 객체에게 특정 작업을 수행하도록 요청

    • 작업 요구 담당 (종업원)

    • setCommand

  • 커맨드(Command): 커맨드 객체에서 구현해야 하는 인터페이스,

    • execute: 리시버에 특정 작업을 처리하라는 지시를 전달

    • undo: 작업 취소

  • 리시버(Receiver): 요구사항을 수행할 때 어떤일을 처리해야 하는지 알고 있는 객체

    • 작업 처리 담당 (주방장)

    • action

  • 커맨드 객체(ConcreteCommand): 특정 행동과 리시버를 연결해줌

    • 주문서

    • execute: 리시버에 있는 메서드를 호출해서 요청된 작업을 처리

    • undo: 실행했던 작업을 원복 on <--> off

핵심 정리

  • 커맨드 패턴을 사용하면 요청하는 객체와 요청을 수행하는 객체를 분리 가능

  • 분리하는 과정에 중심에는 커맨드 객체가 있고, 행동이 들어있는 리시버를 캡슐화함

  • 인보커는 무언가 요청할 때 커맨드 객체의 execute() 메서드를 호출하면 됨

  • 커맨드는 인보커를 매개변수화할 수 있음

    • 실행 중에 동적으로 매개변수화를 설정할 수도 있음

  • execute() 메서드가 마지막으로 호출되기 전의 상태로 되돌리는 작업 취소 메서드를 구현하면 커맨드 패턴으로 작업 취소 기능을 구현 가능

  • 매크로 커맨드는 커맨드를 확장해서 여러 커맨드를 한 번에 호출할 수 있게 해주는 가장 간편한 방법

  • 요청을 스스로 처리하는 '스마트;커맨드 객체를 사용하는 경우도 종종 있음

  • 커맨드 패턴을 활용해서 로그 및 트랜잭션 시스템을 구현할 수도 있음

커맨드 객체 만들기

  • 커맨드 객체는 모두 같은 인터페이스를 구현해야 함

  • 오직 excute() 메서드를 하나만 갖고 있음

public interface Command {
  public void execute();
}
public class LighOnCommand implments Command {
  Light light;

  // 생성자에 커맨드 객체로 제어할 특정 조명의 정보가 전달됨
  // execute() 메서드가 호출되면 light 객체가 바로 그 요청의 리시버가 된다.  
  public LightOnCommand(Light light) {
    this.light = light;
  }
  
  public void execute() {
    light.on();
  }
  
  public void undo() {
    light.off();
  }
}
  • 커맨드 객체를 사용해서 리모콘 만들기

public class SimpleRemoteControl {
  Command slot;
  public SimpleReomteControl() {}
  
  public void setCommand(Command command) {
    slot = command;
  }
  public void buttonWasPressed() {
    slot.execute();
  }
}

NoCommand 객체

  • 커맨드 인터페이스에 따르고 excute() 실행시 아무 동작도 하지 않는 커맨드 객체

  • 일종의 널 객체

    • 딱히 리턴할 객체도 없고 클라이언트가 null을 처리하지 않게 하고 싶을 때 활용

  • 명령이 아직 할당되지 않는 부분에 NoCommand 객체를 넣어서 execute()가 호출되어도 문제가 생기지 않도록

작업 취소 기능 추가하기

public interface Command {
  public void execute();
  public void undeo();
}
  • 마지막으로 실행된 명령을 기록하는 인스턴스 변수를 추가

  • Undo 실행시 기록해 뒀던 커맨드 객체 레퍼런스로 undo() 메서드 호출

public class RemoteControlWithUndo {
  Command[] onCommands;
  Command[] offCommands;
  Command undoCommand;
  
  public RemoteControlWithUndo() {
    onCommands = new Command[7];
    offCommands = new Command[7];
    
    Command noCommand = new NoCommand();
    for(int i=0;i<7;i++){
      onCommands[i] = noCommand;
      offCOmmands[i] = noCommand;
    }
    undoCommand = noCommand;
  }
  
  public void setCommand(int slot, Command onCommand, Command offCommand) {
    onCommands[slot] = onCommand;
    offCommands[slot] = offCommand;
  }
  
  public void onButtonWasPushed(int slot) {
    onCommands[slot].execute();
    undoCommand = onCommands[slot];
  }
  
  public void offButtonWasPushed(int slot) {
    offCommands[slot].execute();
    undoCommand = offCommands[slot];
  }
  
  public void undoButtonWasPushed() {
    undoCommand.undo();
  }
}

여러 동작을 한 번에 처리하기

  • 다른 커맨드를 실행할 수 있는 새로운 종류의 커맨드 객체를 만들어 여러 커맨드를 한번에 실행

public class MacroCommand implements Command {
  Command[] commands;
  
  public MacroCommand(Command[] commands) {
    this.commands = commands;
  }
  
  public void execute() {
    for (int i=0; i<commands.length; i++) {
      commands[i].execute();
    }
  }
}

항상 리시버가 필요한지? 커맨드 객체에서 직접 execute() 로직을 구현하면 안되나?

  • 일반적으로는 리시버에 있는 행동을 호출하는 '더미' 커맨드 객체를 만든다.

  • 물론 커맨드 객체에서 대부분의 행동을 처리해도 되지만

  • 인보커와 리시버를 분리하기 어려워짐

  • 리시버로 커맨드를 매개변수화할 수 없어짐

커맨드로 컴퓨티에이션(computation)의 한 부분(리시버와 일련의 행동)을 패키지로 묶어 일급 객체 형태로 전달할 수도 있다.

  • 커맨드 객체를 생성한 뒤 오랜 시간이 지나도 그 컴퓨테이션을 호출 가능

  • 심지어 다른 스레드에서도 호출 가능

  • 이점을 활용해 커맨드 패턴을 활용하여 스케줄러, 스레드 풀, 작업 큐와 같은 다양한 작업에 적용함

Previous데코레이터 패턴Next전략 패턴

Last updated 10 months ago