logo
Firsttx

FirstTx Overview

FirstTx는 React 19 기반 CSR 앱에서 재방문 속도 · 오프라인 내구성 · 낙관적 UI
한 번에 다루기 위한 3-레이어 툴킷입니다.

  • Prepaint - “마지막 화면”을 DOM 스냅샷으로 저장해 두었다가, 다음 방문 시 React보다 먼저 복원하는 렌더 레이어
  • Local-First - IndexedDB를 단일 소스로 두고, Zod 스키마로 모델을 정의하며, TTL·멀티탭 동기화까지 제공하는 데이터 레이어
  • Tx - UI 업데이트와 서버 요청을 하나의 트랜잭션으로 묶어, 실패 시 안전하게 롤백·재시도·타임아웃을 처리하는 실행 레이어
이 페이지에서 알 수 있는 것
  • FirstTx가 어떤 문제를 해결하려는지

  • Prepaint / Local-First / Tx가 각각 어디에 꽂히는지

  • “나 같은 앱”에 쓸 수 있는지, 대략적인 도입 경로가 무엇인지

설치/코드 예제는 Getting Started 페이지에서 단계별로 다룹니다.


1. 왜 FirstTx가 필요한가요?

일반적인 CSR 앱에서 자주 겪는 상황들입니다.

  • 첫 진입은 SSR/SPA 스켈레톤 덕분에 나름 빠른데,
    • 재방문 / 탭 이동 / 뒤로 가기만 하면 다시 1-2초 동안 흰 화면이나 로딩 스피너가 뜹니다.
  • 사용자가 리스트를 편집하거나 폼을 제출할 때,
    • 낙관적 UI로 “먼저 반영 후 서버 요청”을 하다가
    • 네트워크 에러가 나면 화면 상태가 반쯤만 롤백되어 버립니다.
  • 오프라인/느린 네트워크에서는
    • “마지막으로 보던 상태”조차 복원되지 않아,
    • 페이지에 들어갈 때마다 매번 빈 상태에서 다시 로딩을 기다려야 합니다.

FirstTx는 이런 문제를 세 레이어로 나눠서 다룹니다.

  1. Prepaint로 “마지막 화면”을 기억하고,
  2. Local-First로 로컬 모델을 항상 유지하고,
  3. Tx로 UI 변경 과정을 트랜잭션으로 감쌉니다.

2. 세 레이어 한눈에 보기

Prepaint - “재방문 0ms 화면 복원”

  • 마지막 화면을 DOM + 스타일 스냅샷으로 저장해 두었다가
  • 다음 방문 시 React 번들보다 먼저 해당 화면을 복원합니다.
  • React 하이드레이션이 끝나면 자연스럽게 실제 앱으로 핸드오프합니다.
  • ViewTransition이 가능한 환경에서는 복원 → 실제 렌더를 부드러운 전환 애니메이션으로 감쌉니다.

언제 좋을까요?

  • 데이터 대시보드, 내부 도구, 문서 뷰어처럼
    “같은 화면으로 자주 왔다 갔다 하는” CSR 앱
  • “새로고침/뒤로 가기 했을 때 항상 빈 화면이 먼저 나와서 답답한” UX를 개선하고 싶을 때

Local-First - “IndexedDB 기반 동기 스토어”

  • defineModel로 모델을 정의하면, 그 구조 그대로 IndexedDB에 저장됩니다.
  • Zod 스키마로 타입/무결성을 검증해서 깨진 데이터는 자동 정리합니다.
  • useModel / useSyncedModel 훅으로:
    • 로컬 캐시를 동기적으로 읽고
    • TTL이 지나면 서버와 자동 동기화합니다.
  • 여러 탭에서 같은 모델을 열면, BroadcastChannel로 변경 사항이 탭간 동기화됩니다.

언제 좋을까요?

  • “오프라인에서도 마지막 상태는 보여줘야 하는” 앱
  • “새로고침해도 리스트/폼 상태를 유지하고 싶다”는 요구가 있는 내부 도구
  • IndexedDB를 직접 다루고 싶진 않지만, 브라우저에 내구성 있는 데이터 레이어가 필요할 때

Tx - “트랜잭션 기반 낙관적 UI 실행기”

  • 여러 단계를 가진 작업(로컬 업데이트 + 서버 요청 + 후처리)을
    • 하나의 트랜잭션으로 묶고,
    • 중간에 실패하면 앞 단계들을 **역순으로 보상(compensate)**합니다.
  • 단계별 재시도(선형/지수 백오프), 전역 타임아웃, ViewTransition까지 함께 처리합니다.
  • React 훅 useTx를 사용하면
    • optimistic / rollback / request를 한 번에 구성할 수 있습니다.

언제 좋을까요?

  • “여러 API 호출과 로컬 상태 변경이 섞인 작업을 원자적으로 처리하고 싶을 때”
  • “낙관적 UI를 이미 쓰고 있는데, 실패 케이스에서 화면이 종종 꼬이는” 상황
  • 실패/재시도/롤백까지 DevTools에서 한 번에 추적하고 싶을 때
각 레이어는 독립적으로도 사용할 수 있습니다
  • Prepaint만 붙여 “재방문 빈 화면 제거”에 집중할 수도 있고,

  • Local-First만 써서 IndexedDB 기반 데이터 레이어만 가져갈 수도 있으며,

  • Tx만 써서 기존 상태 관리(예: React Query, Redux 등)에 트랜잭션 실행기만 더할 수도 있습니다.

이 문서 세트에서는 “세 레이어를 함께 사용하는” 시나리오를 기본으로 설명하되, 각 레이어별 문서에서 단독 도입 패턴도 따로 다룹니다.


3. 어떤 앱에 잘 맞나요?

특히 잘 맞는 경우

  • SaaS 대시보드, 내부 어드민, 분석/BI 도구
  • 문서/지식 관리 도구(노션류)처럼 동일 화면 재방문이 잦은
  • “오프라인/느린 네트워크에서도 마지막 상태를 보여줘야 하는” 필드용 도구
  • 이미 React 19를 사용하고 있고, CSR 기반 렌더링이 기본인 프로젝트

과할 수 있는 경우

  • 간단한 랜딩 페이지/마케팅 페이지 (정적 사이트 + SSR만으로 충분한 경우)
  • 페이지 간 이동이 거의 없고, 재방문 UX를 크게 신경 쓰지 않아도 되는 소규모 툴
  • 브라우저 저장소(IndexedDB)에 아무것도 남기고 싶지 않은 민감한 환경

4. 어떻게 도입하면 될까요?

FirstTx는 한 번에 모든 것을 도입하지 않아도 됩니다.
일반적인 추천 순서는 다음과 같습니다.

  1. 1단계 - Prepaint만 도입 (5-10분)

    • Vite/Next 등 번들러에 Prepaint 플러그인을 연결하고
    • 엔트리 포인트를 createFirstTxRoot로 교체합니다.
    • 이 단계만으로도 재방문 시 “마지막 화면을 바로 보여주는” 효과를 얻을 수 있습니다.
  2. 2단계 - Local-First로 데이터 내구성 추가

    • 자주 쓰는 모델 하나(예: CartModel, UserSettingsModel)부터 defineModel로 등록합니다.
    • useSyncedModel로 서버와 동기화하는 훅을 연결합니다.
  3. 3단계 - Tx로 낙관적 UI를 트랜잭션화

    • 기존 “낙관적 UI + fetch” 로직을 Tx의 트랜잭션으로 감싸고,
    • 실패 시 롤백/재시도/타임아웃을 한 번에 다룰 수 있도록 정리합니다.

5. 다음에 읽으면 좋은 문서

  • 바로 손으로 써보고 싶다면Getting Started
  • Prepaint가 정확히 어떻게 DOM을 캡처/복원하는지 궁금하다면Prepaint
  • Local-First의 TTL/버전/멀티 탭 동기화가 궁금하다면Local-First
  • Tx의 재시도/타임아웃/에러 계층이 궁금하다면Tx