State Machine With Generator

CheolHyeon Park·2022년 12월 15일
0

기초지식

목록 보기
15/15

저번에 포스팅한 Generator에 대한 내용을 포스팅하면서 Generator는 State machine으로서 역할을 한다고 정리했다. State Machine이 무엇인지 정리하고자 한다.

정의

State Machine은 간단하게 정리하자면 상태를 가지고 있는 추상기계이다. 유한한 상태를 가진 기계를 Finite State Machine(FSM)이라고 한다. 임의의 주어진 시간동안에 상태를 현재상태(Current State)로 정의하고 어떠한 사건(Event)에 의해 이 상태가 변경될 수 있다. 이를 천이(transition)라고 부른다. transition으로 변경될 수 있는 상태와 변경 요인들의 집합을 State Machine이라고 한다.
말이 어려운데 간단하게 정리하자면 유한한 State를 정의하고 State를 변경할 수 있는 Event를 정의하여 상태 간에 어떠한 이벤트에 의해 State가 변경되는지 추적할 수 있는 다이어그램이라고 생각하면 된다.

[출처] Microsoft Docs, How NFC Class Works?

장점

  • 개발 하기 전에 State를 정의하여 변화를 예측가능하게 해준다.
  • 변화가 예측가능하기 때문에 디버깅이 쉽다.
  • 상태 변화가 머신 내부로 한정되기 때문에 상태관리가 쉽다

State Machine으로서 Generator

State Machine으로서 Generator의 장점을 확인해보고자 한다. 간략한 예제이다.

광고는 간단하게 3가지 상태를 갖는다. INIT,ACTIVE, INACTIVE의 3가지 상태를 갖고 상태를 transition할 수 있는 경우는 다음과 같다고 정의해보자.

  • 신규 광고 등록(REGISTER)
  • 계약 종료(END_OF_CONTRACT)
  • 계약 만기(CONTRACT_EXPIRATION)
  • 계약 연장(CONTRACT_EXTENSTION)

이를 Generator를 통한 상태머신으로 만들면 다음과 같다.

// 상태 정의
const INIT = Symbol("INIT");
const ACTIVE = Symbol("ACTIVE");
const INACTIVE = Symbol("INACTIVE");

// event 정의
const END_OF_CONTRACT = Symbol("END_OF_CONTRACT");
const CONTRACT_EXPIRATION = Symbol("CONTRACT_EXPIRATION");
const CONTRACT_EXTENSION = Symbol("CONTRACT_EXTENSION");
const REGISTER = Symbol("REGISTER");

const print = (...args) => console.log(args[0], args[1])

const AdStateMachine = function* () {
  let state = INIT;
  let transition;
  while(true) {
    if((state === INIT || state === INACTIVE) && (transition === CONTRACT_EXTENSION || transition === REGISTER)) {
      // transition
      state = ACTIVE;
    }

    if(state === ACTIVE && (transition === END_OF_CONTRACT || transition === CONTRACT_EXPIRATION)) {
	  // transition
      state = INACTIVE
    }

    transition = yield state;
  }
}

const adSm = AdStateMachine();
print("InitState: ", adSm.next().value);
print("Register: ", adSm.next(REGISTER).value);  // REGISER 이벤트 발생 transition 발생
print("Current State: ", adSm.next().value);
print("END_OF_CONTRACT: ", adSm.next(END_OF_CONTRACT).value);  // REGISER 이벤트 발생 transition 발생
print("Current State: ", adSm.next().value);
print("CONTRACT_EXTENSION: ", adSm.next(CONTRACT_EXTENSION).value); // REGISER 이벤트 발생 transition 발생
print("Current State: ", adSm.next().value);

/**
  * 결과
  */
// InitState:  Symbol(INIT)
// Register:  Symbol(ACTIVE)
// Current State:  Symbol(ACTIVE)
// END_OF_CONTRACT:  Symbol(INACTIVE)
// Current State:  Symbol(INACTIVE)
// CONTRACT_EXTENSION:  Symbol(ACTIVE)
// Current State:  Symbol(ACTIVE)

Generator가 StateMachine으로서 작동하는 이유

  • Generator는 resume와 suspend를 통해 현재 상태를 저장하고 있을 수 있습니다.
  • next()의 인자를 통해 generator 내부에 값을 전달하고 이를 통해 state를 transition시킬 수 있게 됩니다.

정리

State Machine을 공부하며 Generator의 특성을 좀 더 깊게 이해할 수 있었다. Generator에 대한 이해가 늘어난다면, 활용할 곳이 많은 것 같다. Generator 사용에 익숙해져 보자.

참고

profile
나무아래에 앉아, 코딩하는 개발자가 되고 싶은 박철현 블로그입니다.

0개의 댓글