TypeScript 전환 범위
한국어 번역본
이 문서는 원문(영어)의 한국어 번역이다. 정본은 원문이며, 계약·게이트 판단이 갈리면 원문을 따른다. 원문: docs/gates/typescript-migration-scope.md
이 문서는 Barbelic React 앱의 TypeScript 전환 경계를 확정한다. 현재 단계는 의도적으로 기계적이다. 런타임 동작을 바꾸지 않고 코드 파일을 TypeScript 확장자 공간으로 이름만 바꾼다.
목표
src/react의 모든 코드 파일을 JS/JSX에서 TS/TSX로 옮긴다.- RPC, 인입(import), 관리자, 동기화 경계의 기존 런타임 검증을 유지한다.
- 기존
.mjs테스트를 유지하되, 테스트 러너가node --import tsx --test로 TS 소스를 임포트하게 한다. - 더 작은 후속 PR로 전환을 이어가기 쉽게 만든다.
도구 기준선
typescript,tsx,@types/node,@types/react,@types/react-dom이 개발 의존성(dev dependencies)이다.npm run check:types는tsc --noEmit을 실행한다.npm run check:ts-boundary-gate는 검사 대상 소스 트리 전역에서 소스 수준 TypeScript 억제(suppression) 주석을 금지하고, 명시적any를 검토된 any-boundary 목록에 고정한다.npm run check:ts-strict-gate는 호환용 별칭으로 남아 있다.npm run check:tsconfig는 TypeScript 설정의 형태를 지킨다.npm run check:unused는 전용 GitHub Actions 래칫(ratchet) 단계 안에서만noUnusedLocals와noUnusedParameters를 켠다. 공유 tsconfig 파일들과 기본 로컬npm run check는 그대로 유지된다.npm run test는node --import tsx --test를 사용한다.tsconfig.base.json이 최종 strict 목표다:allowJs: false,checkJs: false,strict: true,noImplicitAny: true,noUncheckedIndexedAccess: true,exactOptionalPropertyTypes: false.tsconfig.json은 현재의 단계적 전환을 위해 기본 설정을 확장한다.src/react/types/에는common,supabase,screenRpc,workout,admin,import,sync,reactComponents,controllers,mobileUi,desktopUi도메인의 공유 타입 골격이 들어 있다. 이들은 공통 값, Supabase 행/RPC, 화면 RPC 페이로드, 운동 초안, 관리자 페이로드, 인입 배치, 동기화 작업, 검사되는 React 컴포넌트 prop 계약을 다루며, 여기에 의도적으로 넓게 잡은 모바일 화면/픽스처 및 데스크톱 화면/픽스처 표현 prop이 더해진다.- Supabase DB 타입은
src/react/types/supabase.ts의 수동 최소 1차 타입을 사용한다. 장기 목표는 원격 프로젝트에서 생성한 Supabase 타입이다:supabase gen types typescript --project-id kobxeylancdimqhfkbnl. - 브라우저/네이티브 브리지 전역은
src/react/global.d.ts에 선언되며, iOSwindow.webkit.messageHandlers브리지, 네이티브 소셜 로그인 이벤트, Barbelic 디버그 전역을 포함한다.
범위 안
현재 범위 스냅샷:
| 영역 | 현재 파일 수 | 목표 |
|---|---|---|
src/react/**/*.js | 0 | .ts로 이름 변경 |
src/react/**/*.jsx | 0 | .tsx로 이름 변경 |
supabase/functions/_shared/*.js | 0 | .ts로 이름 변경 |
supabase/functions/*/index.ts | 3 | .ts 유지 |
tests/**/*.mjs | 라이브 인벤토리 | .mjs 유지. 테스트를 추가할 때 게이트 갱신이 필요해서는 안 된다 |
전환된 영역:
- React 엔트리/루트 파일:
src/react/vite/*.tsx,src/react/app.tsx,src/react/mobileApp.tsx,src/react/desktopApp.tsx src/react/ui/**아래의 React 셸/컴포넌트/화면/픽스처/프리뷰src/react/services와src/react/controllers아래의 서비스/컨트롤러/도메인 모듈directWorkoutWrite,workoutDraftCache,wodupJsonlUpload,supabaseAuth같은 쓰기/인입/인증 모듈src/react/contracts아래의 디자인 계약 코드supabase/functions/_shared아래의 Supabase Edge Function 공유 워커
임포트 지정자 정책
소스의 임포트 지정자는 당분간 기존 .js·.jsx 접미사를 의도적으로 유지한다. 예를 들면 다음과 같다:
import { foo } from "./foo.js";moduleResolution: "Bundler"와 Vite/tsx 툴체인에서 이 지정자들은 전환된 .ts 또는 .tsx 소스 파일로 해석된다. 덕분에 이름 변경 PR이 기계적으로 유지되고, 소란스러운 2차 임포트 재작성을 피할 수 있다.
실제 파일시스템 엔트리 포인트만 갱신했다. index.html, 프리뷰 HTML 파일, Deno Edge Function _shared 임포트가 그 예다.
TypeScript boundary 게이트 정책
이 정책은 docs/gates/typescript-boundary-gate.md에 문서화되어 있다.
소스 구현 파일은 // @ts-nocheck, // @ts-ignore, // @ts-expect-error를 가져서는 안 된다. 기본 npm run check 명령이 check:ts-boundary-gate를 실행하므로, 검사 대상 소스 트리 어디에든 이 억제 주석을 다시 넣으면 로컬과 CI 양쪽에서 실패한다.
현재 @ts-nocheck 예외는 없다. Claude 데스크톱 대시보드 디자인 인테이크 프리뷰 하네스는 타입 검사를 받으며, 임포트 경계 및 디자인 마커 테스트로 계속 보호된다. 앱 컨테이너, 컨트롤러, 리포지토리, 도메인 서비스, RPC 어댑터, 인입/동기화/인증 코드, 모바일 UI, 관리자 운영, 운동 플로우, 데스크톱 일지, 트레이닝 리포트 및 PR 화면, 공유 데스크톱 위젯, 공유 셸 코드가 모두 동일한 무억제(zero-suppression) 정책을 따른다.
명시적 any는 알려진 전환 경계와 외부 데이터 경계에 여전히 존재한다. 특히 Supabase RPC/원시 행 매핑, Wodup JSON 정규화, 브라우저/네이티브 브리지, 컨트롤러 상태, 넓게 잡은 1차 표현 prop이 그렇다. 명시적 any를 포함하는 모든 파일은 검토된 any-boundary 사유와 함께 scripts/check-typescript-boundary-gate.mjs에 등재되어야 한다. 검토되지 않은 새로운 any 위치는 같은 게이트에서 실패한다.
첫 번째 React 컴포넌트 검사 패스는 공유 앱 셸, Vite 루트, 데스크톱 관리자 운영 콘솔을 다룬다. 이들의 재사용 가능한 prop 계약은 src/react/types/reactComponents.ts에 있다.
검사되는 컨트롤러 패스는 appController와 src/react/controllers 아래의 모든 파일을 다룬다. 재사용 가능한 상태 setter, 토스트, 외부 행 경계 타입은 src/react/types/controllers.ts에 있다.
검사되는 플랫폼 컨테이너 패스는 mobileApp, desktopApp, tweaks-panel, contracts/designContract, 그리고 모바일/데스크톱 Vite 루트를 다룬다.
검사되는 모바일 UI 패스는 모든 src/react/ui/mobile/screens/*.tsx 화면 컴포넌트를 다룬다. 1차 화면 prop은 src/react/types/mobileUi.ts에 있고, 표현 경계에서는 의도적으로 넓게 유지하면서도 파일들은 실제 TypeScript 검사 아래에 계속 둔다.
검사되는 데스크톱 UI 패스는 앱이 소유한 데스크톱 표면을 다룬다. 관리자, 즐겨찾기 그룹 편집기, 홈, 일지, 기록표, PR, 인입, 매핑, 온보딩, 프로필, 검색, 플랜 편집기, 운동 플로우, 셸 인접 화면이 여기에 포함된다. 프리뷰 하네스와 픽스처는 Claude Design 로컬 전용 자료이며 이 레포지토리에는 더 이상 존재하지 않는다(docs/process/design-codex-transfer-contract.md).
검증 기준선
모든 TypeScript 전환 단계는 동일한 로컬 기준선을 실행해야 한다:
npm.cmd run check:unused
npm.cmd run check:types
npm.cmd run check
npm.cmd run buildNode 테스트 러너는 node --import tsx --test를 통해 TypeScript 소스를 임포트한다. 화면 RPC 계약 테스트는 검증기와 페이로드 계약이 어긋날 때 fail-closed로 실패함을 증명하고, 프런트엔드 임포트 경계 테스트는 원시 리포지토리 로더가 앱을 마주하는 UI/컨트롤러 경로에 들어오지 못하게 막는다.
범위 밖
- SQL 파일과 Supabase 마이그레이션
- CSS, HTML, PNG, SVG, Markdown, TOML 및 기타 비코드 에셋
- 기존
.mjs테스트를 TypeScript로 재작성하는 것 - 이번 1차 패스에서 원격 프로젝트로부터 전체 Supabase DB 타입을 생성하는 것
- 기능 동작 변경, UI 재설계, 인입 파이프라인 동작 변경, DB 스키마 변경
순서
- TypeScript 도구와
check:types를 추가한다. - 공유 앱/도메인/RPC 페이로드 타입을 추가한다.
- 1차 Supabase 타입 전략을 추가한다.
- JS/JSX 소스 파일을 TS/TSX로 이름 변경한다.
- 파일시스템 엔트리 포인트와 테스트를 이름이 바뀐 파일에 맞춰 조정한다.
- 이후 전용 재작성이 있기 전까지 소스 임포트 지정자를 그대로 유지한다.
- 데스크톱 디자인 인테이크 프리뷰 하네스를 포함해 모든 임시
// @ts-nocheck헤더를 제거한다. - boundary 게이트를 Green으로 유지해 TypeScript 억제 주석이 코어/앱/데이터 경로로 돌아오지 못하게 하고, 새로운 명시적
any사용은 검토를 받게 한다.
완료 기준
src/react아래에.js나.jsx파일이 남아 있지 않다.supabase/functions/_shared아래에.js파일이 남아 있지 않다.- 기존
.mjs테스트가.mjs로 남아 있고 TS 소스에 대해 통과한다. npm run check:types,npm run check,npm run build가 통과한다.- RPC/인입/관리자 페이로드 경계에 런타임 검증이 계속 활성 상태로 남는다.