"아직도 if-else 문으로 복잡한 로직을 처리하시나요?" 펌웨어 설계의 꽃이라 불리는 상태 머신(FSM) 패턴을 통해 스파게티 코드를 깔끔하게 정리하는 아키텍처 설계법을 전수해 드립니다.
반갑습니다, 후배님들! 10년 차 펌웨어 아키텍트입니다. 😊 STM32 실무를 하다 보면 센서 읽고, 모터 돌리고, 통신까지 해야 하는데 코드가 걷잡을 수 없이 복잡해지는 순간이 오죠? 특히 '플래그 변수'가 10개를 넘어가기 시작하면 내가 짠 코드인데도 분석이 안 됩니다. 오늘 그 지옥에서 탈출시켜 드릴게요!
첫 번째 주요 섹션: 왜 if-else는 위험할까? 🤔
우리가 흔히 범하는 실수는 "A가 눌리면 B를 해라"라는 조건문을 무작정 추가하는 것입니다. 하지만 실무에서는 '대기 중일 때' 버튼이 눌린 것과 '동작 중일 때' 버튼이 눌린 것이 전혀 다르게 동작해야 하죠. 이런 상황을 고려하지 않으면 코드는 점점 꼬이게 됩니다.
⚠️ 주의하세요!
중첩된 if문 안에 수많은 플래그 변수들이 섞이면 시스템이 어떤 상태인지 예측 불가능한 '블랙박스'가 되어버립니다. 이는 곧 찾기 힘든 치명적인 버그로 이어집니다.
중첩된 if문 안에 수많은 플래그 변수들이 섞이면 시스템이 어떤 상태인지 예측 불가능한 '블랙박스'가 되어버립니다. 이는 곧 찾기 힘든 치명적인 버그로 이어집니다.
두 번째 주요 섹션: 유한 상태 머신(FSM)의 개념 📊
유한 상태 머신은 시스템이 가질 수 있는 유한한 수의 상태를 정의하고, 입력(이벤트)에 따라 상태가 어떻게 변하는지 설계하는 수학적 모델입니다. 펌웨어에서는 이를 통해 로직을 명확하게 분리할 수 있습니다.
[Image of finite state machine diagram for embedded system]상태 머신 구성 요소
| 구성 요소 | 설명 | 구현 방법 |
|---|---|---|
| State (상태) | 시스템의 현재 상황 (IDLE, RUN, ERROR) | enum 상수로 정의 |
| Event (이벤트) | 상태 전이를 일으키는 트리거 | 함수 입력 또는 플래그 |
세 번째 주요 섹션: C언어 구현 가이드 🧮
📝 switch-case 패턴
가장 표준적이고 가독성이 좋은 구현 방식은 enum과 switch-case를 활용하는 것입니다.
typedef enum {
STATE_IDLE,
STATE_RUNNING,
STATE_ERROR
} SystemState_t;
void Main_Process(void) {
static SystemState_t currentState = STATE_IDLE;
switch(currentState) {
case STATE_IDLE:
if(isButtonPressed()) currentState = STATE_RUNNING;
break;
case STATE_RUNNING:
if(checkError()) currentState = STATE_ERROR;
break;
case STATE_ERROR:
// 에러 처리 로직
break;
}
}
마무리: 핵심 내용 요약 📝
FSM 패턴은 펌웨어의 안정성을 책임지는 핵심 설계 기술입니다.
- 구조화: 모든 로직을 상태별로 분리하여 관리하세요.
- 신뢰성: 예기치 못한 상태로의 전이를 원천 차단할 수 있습니다.
- 확장성: 새로운 기능 추가 시 기존 코드를 건드리지 않고 새로운 case만 추가하면 됩니다.
여러분도 오늘부터 if-else 지옥에서 벗어나 예술적인 코드를 짜보시길 바랍니다. 😊
자주 묻는 질문 ❓
Q: 상태가 20개가 넘어가면 어떻게 하나요?
A: 그럴 때는 계층적 상태 머신(HSM)을 고려해야 합니다. 큰 상태 안에 세부 상태를 두어 복잡도를 낮추는 기법입니다.
Q: 인터럽트 서비스 루틴(ISR) 내에서 FSM을 직접 돌려도 되나요?
A: ISR에서는 이벤트만 발생(플래그 설정)시키고, 실제 FSM 로직은 메인 루프에서 처리하는 것이 안전합니다.

