XState(1)

최근 상태 관리 라이브러리에 대한 리서치를 하다가 관심있게 보고있던 XState를 공부해보고 정리할 겸 작성. 내용이 너무 많을 것 같아서 틈날때마다 업데이트 해나아갈 예정이다.

Xstate
XState는 유한 상태기과 상태도를 생성, 해석, 실행하기 위한 라이브러리이며, 해당 기계.의 호출을 배우.로 관리하기 위한 라이브러리이다.
알아야할 개념은 FSM, 상태도, 배우 모델들에 대한 내용인데 이 곳 에 읽어볼만한 레퍼런스들이 있다. 과거 대학교에서 이산 수학 강의를 들었을 때 마지막 챕터였던 FSM에 대해서 수학의 정수라고 말씀주셨던 기억이 난다.
위키 의 내용을 보자면 유한한 개수의 상태를 가질 수 있는 오토마타로서, 오직 하나의 상태(주)만을 가지게 되고 어떠한 사건(이벤트)에 의해 한 상태에서 다른 상태로 변환 할 수 있는 전이(전환)라고 하는데, 상태와 전이의 집합을 FSM으로 정의하는 것 같다.
많이 알려진 활용 분야중에 게임에서 몬스터의 행동 패턴, 공학에서의 논리 회로등 다양한 분야에서 쓰이고 있고, 요약하자면 아래와 같은 조건들로 정의가 된다.
  • 유한개의 상태 (주)
  • 유한개의 사건 (이벤트)
  • 초기 상태
  • 현재 상태와 사건을 다음 상태로 결정하는 전이 함수 (변환 기능)
  • (비어있을 수 있는) 최종 상태 집합 (최종 상태)
  • 주요 내용은 공식 문서 를 바탕으로 진행하며 설치는 아래와 같이 한다.
    npm install xstate --save
    yarn add xstate
    

    개요
    공장 기능인 createMachine 을 이용하여 상태기혹은 상태도을 생성할 수 있다.
    import { createMachine } from 'xstate';
    
    const promiseMachine = createMachine({
      id: 'promise',
      initial: 'pending',
      states: {
        pending: {
          on: {
            RESOLVE: { target: 'resolved' },
            REJECT: { target: 'rejected' }
          }
        },
        resolved: {
          type: 'final'
        },
        rejected: {
          type: 'final'
        },
      },
    });
    
    id 는 기계.의 고유값이면서 자식 상태 노드 신분증의 기현이 된다.initial 은 초기 상태 노드를 지정하며, states 는 각각의 자식 상태를 정의한다.
    위 FSM의 개념에서의 전이(전환)은 resolvedrejected 라는 상태로 지정하며, 각 각의 상태는 final 이라는 기계.이 종료에 도달하는 상태임을 지정한다.
    생성한 기계.을 해석하고 실행하려면 interpret 를 이용하여 통역원를 추가해야 한다. 아래와 같이 사용 가능하다.
    import { createMachine, interpret } from 'xstate';
    
    const promiseMachine = createMachine({
      /* ... */
    });
    
    const promiseService = interpret(promiseMachine).onTransition((state) =>
      console.log(state.value)
    );
    
    // Start the service
    promiseService.start();
    // => 'pending'
    
    promiseService.send({ type: 'RESOLVE' });
    // => 'resolved'
    
    그리고 createMachine 으로 생성한 코드는 이 곳 에서 시각화 하고 실행해 볼 수 있다.

    주.
    상태는 특정 시점의 추상적 표현이다. FSM은 주어진 시간에 유한한 수의 상태중 하나만 가능하다. 상태 정의는 아래와 같이 정의 하고 확인할 수 있다.
    const lightMachine = createMachine({
      id: 'light',
      initial: 'green',
      states: {
        green: {
          /* ... */
        }
        // ...
      }
    });
    
    console.log(lightMachine.initialState);
    // State {
    //   value: 'green',
    //   actions: [],
    //   context: undefined,
    //   // ...
    // }
    
    프레젠테이션객체는 JSON직렬화가 가능하며 아래와 같은 속성이 있다.
  • 값:현재 상태 값 (예를 들어 {red:'보행'}
  • 배경:상태의 현재 컨텍스트
  • 이벤트:해당 상태로 전환을 트리거한 이벤트오브젝트
  • 행동:실행할 액션의 배열
  • 이벤트:액티비티가 실행되면 맞아요.중지되면 가짜
  • 기록:이전 상태 인스턴스
  • 원:상태 노드의 원.프로퍼티로 정의된 메타 데이터
  • 완료:상태가 최종 상태를 나타내는지에 대한 여부

  • 프레젠테이션의 메소드와 속성들

    주 정부.일치(ParentStateValue)
    주 정부.가치 01 명가 주어진 parentStateValue 의 자집인지 확인한다. 예를들어 state.value{ red: ‘stop’ } 이라면?
    console.log(state.value);
    // => { red: 'stop' }
    
    console.log(state.matches('red'));
    // => true
    
    console.log(state.matches('red.stop'));
    // => true
    
    console.log(state.matches({ red: 'stop' }));
    // => true
    
    console.log(state.matches('green'));
    // => false
    
    만약 여러 상태에 대한 시합를 원한다면?
    const isMatch = [{ customer: 'deposit' }, { customer: 'withdrawal' }].some(
      state.matches
    );
    
    

    주 정부.다음 이벤트
    현재 상태에서 가능한 다음 전환을 확인해볼 수 있다.
    const { initialState } = lightMachine;
    console.log(initialState.nextEvents);
    // => ['TIMER', 'EMERGENCY']
    

    주 정부.개변
    이전 상태로부터 변화되었는지에 대한 여부를 알수 있다. 상태가 아래와 같다면 changed 로 간주한다.
  • 이전 값과 값이 같지 않다
  • 어떠한 새로운 액션 (부작용)가 실행되었다.
  • const { initialState } = lightMachine;
    
    console.log(initialState.changed);
    // => undefined
    
    const nextState = lightMachine.transition(initialState, { type: 'TIMER' });
    
    console.log(nextState.changed);
    // => true
    
    const unchangedState = lightMachine.transition(nextState, {
      type: 'UNKNOWN_EVENT'
    });
    
    console.log(unchangedState.changed);
    // => false
    
    최초 상태(히스토리가 없는 것)는 undefined 이다.

    주 정부.완성
    이 상태가 최종 상태인지에 대한 여부를 알 수 있다.
    const answeringMachine = createMachine({
      initial: 'unanswered',
      states: {
        unanswered: {
          on: {
            ANSWER: { target: 'answered' }
          }
        },
        answered: {
          type: 'final'
        }
      }
    });
    
    const { initialState } = answeringMachine;
    initialState.done; // false
    
    const answeredState = answeringMachine.transition(initialState, {
      type: 'ANSWER'
    });
    answeredState.done; // true
    

    주 정부.ToString()
    상태값의 패스에 대한 모든 표현의 문자열 배열을 리턴한다.
    console.log(state.value);
    // => { red: 'stop' }
    
    console.log(state.toStrings());
    // => ['red', 'red.stop']
    
    
    문서에서는 CSS 클래스나 데이터 속성같은 문자열 기반환경에서 유용하게 사용될 수 있다고 하는데 아마 해당 요소에 컨디션의 가치 01 명값을 바로 사용하면 되겠지 라는 생각이 들었다.
    이후 내용은 조금 더 내용을 읽어보고 작성해야할 것 같다.
    계속

    좋은 웹페이지 즐겨찾기