State Machine

1,925 단어·4 분·원문(.md)

state machine은 시스템이 유한한 개수의 상태들중 하나에 있으며, 입력(event)에 따라 다른 상태로 전이(Transaition) 되는 개념을 가진 이산적인 수학 모델이다.

즉 추상기계로, 이러한 기계는 한 번에 오로지 한 개의 상태를 가지게 되며, current state와 같이 임의의 주어진 시간의 상태를 칭한다.

특정한 유한 오토마톤(이산적인 수학 모델)은 현재 상태로부터 천이 상태와, 이러한 천이를 유발하는 조건들의 집합으로서 정의가 된다.

천이: 양자역학에서, 입자가 한 정상 상태(定常狀態)에서 어떤 확률을 가지고 다른 정상 상태로 옮겨가는 일. 전이(轉移)와 동의어

cs 전반에 쓰이며, 프로그래밍이나 통신 프로토콜 워크플로우 엔진 등에서 자주 사용되는 모데링라고 볼 수 있다.

  • STATE: 현재 시스템이 머무는 하나의 상태
  • EVENT/INPUT: 상태 변화를 유발하는 외부의 자극
  • TRANSITION: 한 상태에서 다른 상태로의 전이
  • ACTION: 전이 중 또는 상태 진입/이탈시 수행되는 동작
  • INITIAL STATE: 초기 시작 상태
  • FINAL STATE: 종료 상태(있을수도 없을수도 있음)

예를들어 신호등을 떠올려보자 신호등은 유한상태머신으로(FSM) 상태의 개수가 유한한 경우를 볼 수 있다.

예를들어 파란불 빨간불 (노란불)이 state가 되는 것이고 event는 시간이 지나는 것이다.

그리고 시간이 지남에 따라 하는 동작은은 빨간불에서 파란불(중간에 노란불이 낄수도 있다)이 되듯이 변화하는 것을 볼 수 있다.


Finite, Infinite #

보통의 스테이트 머신은 유한개 혹은 무한개로 구성되는 finite state machine or infinite state machine으로 구분이 되어가고 있지만, real world에서는 주로 finite state machine으로 프로덕트가 구성이 되고, 그렇기에 일반적으로 state machine이라 함은 finite state machine이라고 통칭해도 된다.

자 이제 FSM을 알아봤지만 한가지 의문이 들 것이다 프로그래밍에서 if else or switch-case를 타고 이벤트문을 처리해도 전혀 문제도 없고 다를게 없어보이는데 도대체 이 상태 머신이란 무엇이고 구현하는데에만 시간이 더 걸리는 것을 왜 사용하는 것일까? 왜 상태 자체를 하나의 오브젝트가 관리하며, 동작을 따로따로 분리를 해놓는 것일까?

이런 고민은 당연히 해볼만한 고민이고 하지않고 좋다고 생각하는게 더 문제이니 이런 고민을 했다면 칭찬드린다. (대체로 스테이트 머신 라이브러리는 그대로 갖다쓰기가 어렵고 어차피 구조만 가져오고 내부 구현은 새로 쫙 다시해야될 때도 있어서 부지기수라 웬만해서는 다들 직접 구현한다.)

일단 state machine을 사용하는 이유는 안정성 때문인데, 수학적 모델은 그 정의 자체만으로도 안정성을 가지고 있다.

통제 가능한 변인을 제어하여 원하는 아웃풋을 내기 때문인데 if-else나 switch-case는 설계 자체에 결함이 없더라도 구현중에 변수 오염 혹은 생각치못한 else문에 대한 대응이 어려운 경우의 수가 존재하며 멀티 스레딩과 같은 동시성 환경일 때의 변수 오염의 문제도 심각해진다. (state도 동시성에 대한 처리가 필요없는것은 아니지만 핸들링할 수 있는 범위가 줄어들게 된다.)

물론 else문에 대한 집합의 여집합이 공집합이 될 수 있는 전제가 깔린 요구사항이라면, if else를 사용해도 상관은 없겠다라는 생각을 필자는 가지고있다.


init, idle, processing, error, recovery #

state 머신으로 정의할 수 있는 모델들에게 공통적으로 나타나는 패턴이 제목과 같은데 하나씩 알아보겠다.

  1. init: 초기 상태를 초기화하는 동작을 수행하는 상태다
  2. idle: 초기화가 끝마치면 idle state로 외부 동작이나 이벤트를 감지하기 위해 대기하는 상태다.
  3. processing: 외부 입력이 감지가 되면 processing state로 전이 대어 맞는 처리 동작을 진행한다.
  4. error: processing 도중 오류가 검출되어 작업을 중단하고 오류코드를 분석한다.
  5. recovery: 분석된 오류 결과를 토대로 복구하는 동작을 진행한다.

recovery가 끝마치면 다시 idle로 돌아가 감지하고 전이하는 동작의 반복이다.

위의 예시에서 스테이트 머신만의 장점을 보면 반드시 설계한대로 플로우가 흐를 수 있고, 장애가 발생해도 state에 따라 발생할 수 있는 케이스를 정확하고 단순하게 파악할 수 있다. 디버깅이 빨라진다는 얘기다.

정해진 이벤트를 통해서만 전이되기 때문에 설계자는 모든 플로우를 주관해 설계가 가능하며 구현자도 설계 문서만 보고도 설계와 똑같이 구현할 수 있으며 파악도 할 수 있다. 설계 자체도 단순해지며 멀티스레딩이나 프로세싱 환경과 같은 기타 외부 요인에도 오염이 되지 않는다. 왜냐면 해당 상태가 되기위한 조건이 이미 정해진 이벤트 규약이기 때문에 안정된 실행 환경을 보장한다.

전체적인 흐름이 유기적이며 명확해지기도 한다.

세상이 발전하고 풀어가는 문제가 많아짐에 따라 우리가 소프트웨어로 구현해야할 동작들은 가지각색이며 복잡하다. 모든 케이스는 인간이 검출해낼 수는 없지만, 유연하게 예외 케이스들을 검출하고 안정적인 동작을 강제할 수 있는, 패턴이 바로 state machine 패턴이다. state machine이라는 모델을 통해 우리는 더욱 더 안정적이며 확장가능한 코드를 작성해 볼 수 있을 것이라고 생각하지만.

과연 지금 내가 구현하는 비즈니스 요구사항이 state machine이 꼭 필요한가는 고민해보는것을 추천한다.

Back-End/state_machine2.md