[ARCHIVED 2026-08-19] 역사 자료 — 현행 규범이 아니다. 아카이브 사유와 대체 문서는 docs/README.md의 Archive 섹션을 참조.
React 앱 소스 아키텍처
한국어 번역본
이 문서는 원문(영어)의 한국어 번역이다. 정본은 원문이며, 계약·게이트 판단이 갈리면 원문을 따른다. 원문: docs/archive/feature-slice-architecture.md
갱신: 2026-06-14
이 프로젝트는 이제 React 앱을 유일한 프런트엔드 소스로 취급한다.
구 바닐라(vanilla) 프런트엔드 폴더들은 아카이브되지 않고 제거되었다. Claude Design과 Codex는 그 경로들을 참조로 사용해서는 안 된다.
정본(source of truth)
- 앱 진입점:
index.html->src/react/vite/main.jsx - React 표면:
src/react/ - Supabase/데이터 파사드:
src/react/services/barbelicApi.js - Supabase 리포지토리/인증/매퍼 모듈:
src/react/services/barbelicRepository.js,src/react/services/supabaseAuth.js,src/react/services/barbelicMappers.js - 데이터 로딩·부트스트랩 전략:
docs/architecture/data-loading-strategy.md - 디자인 마커 계약:
src/react/contracts/designContract.js - 웹 앱 매니페스트:
public/manifest.webmanifest - 오프라인 서비스 워커 지원: 현재는 제거됨. 필요하면 별도로 복원한다
소유권 경계
Claude Design이 소유하는 것:
- 새로운 순수 UI 모듈이 도입될 때의
src/react/ui/** src/react/ui/screens/HomeScreen.jsx,src/react/ui/screens/SessionScreen.jsx,src/react/ui/screens/WorkoutFlow.jsx같은 순수 UI 화면src/react/ui/styles/**- 프레젠테이션 마크업, 컴포넌트 위계, 시각 상태, 레이아웃, 애니메이션, fixture 프리뷰
Codex가 소유하는 것:
src/react/services/**src/react/contracts/**- 데이터 하이드레이션, Supabase 읽기/쓰기, 인증, 영속화, 테스트
- 순수 UI 화면으로 props/콜백을 전달하는 컨테이너 배선
목표 방향
단기 마이그레이션은 React 내부의 컨테이너/프레젠테이셔널 분리다:
src/react/
app.jsx thin compatibility export for GymApp
appController.jsx current composition root
vite/
main.jsx Vite entry and viewport shell
services/
barbelicApi.js ESM data/auth facade
barbelicRepository.js Supabase reads/writes
supabaseAuth.ts Supabase client and provider-neutral auth helpers
barbelicMappers.js DB row <-> app data mapping
barbelicShared.js shared constants and pure helpers
contracts/
designContract.js living data-lg contract
ui/
screens/
SessionScreen.jsx Claude-owned presentational screen
HomeScreen.jsx Claude-owned presentational screen
RecordsDetail.jsx Claude-owned record detail screen
PrTools.jsx Claude-owned PR management screens
ProfileScreen.jsx Claude-owned profile presentational screen
fixtures/
sessionFixture.js Claude preview data
styles/
styles.css Claude-owned app CSS
session.css future Claude-owned screen CSSsrc/react/ui/**는 Supabase, barbelicApi, 영속 스토리지를 임포트해서는 안 된다. 열린 패널, 인라인 에디터, 스와이프 위치, 드래그 상태, 모달 상태, 일시적 토스트 표시 같은 UI 전용 로컬 상태는 가질 수 있다.
서버 데이터 변경은 props/콜백을 통해 이동한다:
<SessionScreen
today={today}
visibleMonth={visibleMonth}
sessionsByDate={sessionsByDate}
selectedDate={selectedDate}
selectedDateSessions={selectedDateSessions}
selectedSession={selectedSession}
conditionByDate={conditionByDate}
monthSummary={monthSummary}
onSelectDate={handleSelectDate}
onChangeMonth={handleChangeMonth}
onGoToday={handleGoToday}
onOpenSession={handleOpenSession}
onCloseSession={handleCloseSession}
onCreatePlan={handleCreatePlan}
onEditPlan={handleEditPlan}
onStartWorkout={handleStartWorkout}
onUpdateSession={handleUpdateSession}
onDeleteSession={handleDeleteSession}
onSetCondition={handleSetCondition}
/>동결된 화면 props 계약은 다음 문서에 기록되어 있다:
docs/contracts/session-screen-props.mddocs/contracts/workout-screen-props.md
데이터 계약
세션 데이터는 위계를 명시적으로 유지해야 한다:
{
id: "uuid",
source: "sessions",
status: "completed",
date: "2026-06-09",
title: "벤치프레스 외 1종목",
summary: "2종목 · 5세트",
exercises: [
{
id: "exercise-id",
name: "벤치프레스",
review: "오늘은 락아웃이 안정적이었음",
sets: [
{ id: "set-id", reps: 5, load: 60, difficulty: null, memo: "" }
]
}
]
}그 구분이 중요할 때, 완료된 운동 기록에는 source: "sessions"를, 계획되었거나 놓친 기록에는 source: "planned_sessions"를 사용한다.
디자인 계약
src/react/contracts/designContract.js가 data-lg-* 마커의 정본이다.
Claude는 PR 설명에서 새 마커를 요청할 수 있지만, 계약에 등록하고 테스트를 통과 상태로 유지하는 것은 Codex다. 마커 계약은 기능적 통합 표면이지 레이아웃이나 시각적 제약이 아니다.
SessionScreen 파일럿에서 Claude는 세션 객체에 source: "sessions" | "planned_sessions"를 유지하고, onDeleteSession(sessionId)가 아니라 onDeleteSession(session)을 호출해야 한다.