UX 패턴을 상태 모델로 바꾸는 방법
Loading, Empty, Error, Success를 코드에서 어떻게 표현할까 UI 상태 모델링, 서버 상태 분리, 예외 상태
UX 패턴을 상태 모델로 바꾸는 방법
먼저 던질 질문
Loading, Empty, Error, Success를 코드에서 어떻게 표현할까
핵심 관점
상태 모델링은 개발자의 내부 정리가 아니라 사용자 경험을 명확히 나누는 일이다. 사용자가 다르게 느끼는 상태는 코드에서도 다르게 표현되어야 한다.
구현 품질로 이어지는 장면
목록 화면을 loading, success, empty, filteredEmpty, error로 나눈다.
폼 제출을 idle, validating, submitting, success, failed로 나눈다.
운영에서 깨지는 흐름
data가 없으면 무조건 Empty를 보여준다.
isLoading과 isError가 동시에 true가 될 수 있는 모순 상태를 만든다.
구현 사례와 근거
좋은 상태 모델은 사용자의 해석 차이를 반영한다
UX 패턴을 상태 모델로 바꿀 때 가장 중요한 기준은 데이터 구조가 아니라 사용자의 해석이다. 데이터가 없다는 사실 하나에도 첫 사용, 검색 결과 없음, 권한 없음, 오류, 필터 결과 없음이 섞일 수 있다.
이 상태들을 코드에서 구분하면 문구, 액션, 접근성, 테스트가 자연스럽게 나뉜다. 반대로 empty 하나로 뭉치면 사용자는 다른 문제를 같은 안내로 받는다.
실무 해석
XState는 상태, 전이, 이벤트를 명시적으로 모델링해 복잡한 앱 로직을 다룬다. TypeScript의 discriminated union은 kind나 status 같은 공통 필드로 분기를 좁혀 불가능한 조합을 줄인다.
TanStack Query도 서버 상태를 pending, error, success 같은 데이터 상태와 fetching, paused, idle 같은 fetch 상태로 나눈다. 이 구분은 로딩 중, 백그라운드 갱신 중, 오프라인으로 멈춤을 같은 UI로 처리하지 않게 만든다.
구현 판단 기준
- 사용자에게 다른 의미를 가진 상태를 분리한다
- 불가능한 상태 조합을 타입으로 막는다
- 서버 상태와 화면 표시 상태를 구분한다
자주 빠지는 함정
boolean flag를 계속 추가하면 상태가 많아지는 것이 아니라 모순이 많아진다. 상태 이름은 UI의 의미를 담아야 한다.
추가로 비교할 구현 사례
- 목록 상태, 폼 제출 상태, 파일 업로드 상태를 state machine으로 표현한다
- boolean flag가 많아 모순 상태가 생기는 예를 만든다
- Discriminated Union과 서버 상태 분리 예시를 추가한다
구현 품질 질문
- 디자이너도 이해할 수 있는 상태 이름인가
- 불가능한 상태를 코드로 막는 예시가 있는가
출처
- Stately, XState Docs: https://stately.ai/docs
- TypeScript Handbook, Narrowing: https://www.typescriptlang.org/docs/handbook/2/narrowing.html
- TanStack Query, Queries: https://tanstack.com/query/latest/docs/framework/react/guides/queries
- Nielsen Norman Group, 10 Usability Heuristics for User Interface Design: https://www.nngroup.com/articles/ten-usability-heuristics/