서류 첨부 플로우를 공용 상태 머신으로 통합
방어 코드를 덧대면 같은 버그가 이름만 바꿔 재발할 구조가 남기에, 흐름 네 개를 사용자 액션 기준의 상태 머신 하나로 합쳤습니다.
2026.08 단독 설계 및 구현
문제
파일 선택부터 검증, 업로드, 상태 반영까지가 useEffect 체인으로 연결되어 있었습니다. effect가 상태 변화에 반응해 다시 상태를 바꾸는 구조라 재현 조건 없이 레이스 컨디션과 무한 루프가 터졌고, 실제로 요청이 폭주하거나 유실되는 문제로 이어졌습니다. 같은 성격의 흐름이 신규 계약, 재계약, 추가 계약, 재첨부 네 갈래로 각자 구현되어 한 곳을 고쳐도 나머지는 그대로였습니다.
검토와 판단
- A
effect에 가드 플래그와 요청 취소를 덧대는 방어 — 당장의 레이스는 막히지만 새 상태가 추가되면 같은 종류의 버그가 재발. 네 흐름에 각각 적용해야 함
- B
흐름별로 상태 관리를 각각 정리 — 흐름마다 맥락이 달라 이해는 쉬우나, 네 벌을 계속 나란히 유지해야 해서 지금의 분기 문제가 그대로 남음
- C (채택)
네 흐름을 사용자 액션 기준 공용 상태 머신으로 통합 — 전이 트리거를 사용자 액션으로 한정해 effect 연쇄를 끊고, 허용되지 않는 전이는 타입과 구조에서 표현조차 되지 않게 함
원인은 방어가 부족해서가 아니라 effect가 상태 변화에 반응해 다시 상태를 바꾸는 구조 자체였습니다. 이 구조를 두고 방어만 더하면 조건이 하나 늘 때마다 같은 버그가 다시 성립합니다. 네 흐름의 차이는 시작 지점과 서류 목록일 뿐 전이 규칙은 같았기에 하나로 합치는 비용도 예상보다 낮았고, 상태 머신 라이브러리도 검토했지만 상태 네 개 규모에 학습과 번들 비용이 과해 판별 유니온으로 직접 정의했습니다.
실행
네 흐름을 판별 유니온 상태 머신 하나로 통합 — idle, uploading, confirming, failed 네 상태에 전이 트리거를 사용자 액션으로 한정
useEffect로 이어지던 로직을 모두 사용자 액션에 맞춰 상태가 변하도록 구조 변경
결과
유저당 재시도 횟수 58% 감소
계약 완주율 94% 유지
회고 상태 변화의 기준을 정리한 작업이었습니다. 사용자 액션에 의한 변화는 이벤트 핸들러에 두고, useEffect에는 액션이 아닌 부가 효과만 남깁니다. effect가 서로 엮이기 시작하면 추적이 어려운 구조가 되므로, effect 자체를 최소화하는 것이 유지보수의 출발점이라고 생각하게 됐습니다.
