정의

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

유한한 State를 정의하고 State를 변경할 수 있는 Event를 정의하여 상태 간에 어떠한 이벤트에 의해 State가 변경되는지 추적할 수 있는 다이어그램이라고 생각하면 된다.

https://velog.velcdn.com/images/fepanbr/post/d54e1d71-2b79-4e47-a79c-b86ca2f8a705/image.png

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

장점

State Machine으로서 Generator

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

https://velog.velcdn.com/images/fepanbr/post/2da444e2-4510-4cb5-a7ef-67708df34aa3/image.jpg

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

이를 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으로서 작동하는 이유