feat: 기능 추가 과정중

This commit is contained in:
donghyeon-ka
2026-07-30 15:58:20 +09:00
parent d3ef801fe6
commit 6c52cdb916
648 changed files with 126325 additions and 6680 deletions
@@ -57,17 +57,19 @@ P0/P1 acceptance와 P2 recipe 기본값은 `LOCAL_TEMPLATE_READY`다. 다만 실
| 영역 | 현재 판정 | 근거 | 필요한 다음 상태 |
| --- | --- | --- | --- |
| 부트·런타임 설정 | 준비됨 | `src/bootstrap`, runtime schema, release 검사 | 현 상태 유지, TS 전환 시 동일 게이트 유지 |
| 계층 의존 방향 | 부분 준비 | `.dependency-cruiser.cjs`, `src/application/ports` | inbound/outbound 명명과 `contracts` 소유권까지 집행 |
| application facade | 준비됨 | typed input/output catalog, provider, production composition test | feature input use case를 contribution으로 확장 |
| HTTP client | 준비됨 | path/search/body projection, runtime timeout/retry, abort/cleanup test | feature gateway 뒤에서 사용 |
| retry | 준비됨 | HTTP 단일 소유, runtime max attempts, Query retry off, logical execution당 bounded diagnostics | terminal event 중복 방지 계약 유지 |
| 오류 모델 | 부분 준비 | error registry와 normalization 존재 | typed discriminated union과 계층별 mapper |
| 검증 | 준비됨 | runtime/API/route/form Zod parse 결과를 실행 경계에서 사용하고 domain invariant와 분리 | feature별 schema 소유권 유지 |
| 계층 의존 방향 | 준비 | dependency-cruiser + TS-aware static graph, unresolved/parse/layer/cycle negative fixture | 새 rule shape와 source extension도 같은 fail-closed graph에 추가 |
| application facade | 준비됨 | module-augmented feature input registry, typed output catalog, provider, production composition test | feature input contribution과 제거 gate 유지 |
| REST HTTP client | 준비됨 + hardening delta | reference vertical의 path/search/body projection, attempt timeout/retry, abort/cleanup`COMPOSED` | auth fail-close/final invariant, total deadline, bounded decoder, status/media/CSRF/conditional/pagination은 `DESIGNED_NOT_IMPLEMENTED` |
| Browser RPC 공통 계약/runtime | 준비됨/미조립 | V3 operation/profile registry, typed application port, bounded unary/server-stream lifecycle와 unavailable adapter는 `AVAILABLE_NOT_COMPOSED` | actual descriptor/generated client, protocol transport, proxy/provider/browser conformance |
| GraphQL·Connect·gRPC-Web·Protobuf REST Gateway 제품 adapter | 설계됨/제품 미선택 | wire dependency/generated source/provider는 없고 VD-26/VD-27/VD-29/VD-30 production contract 승인 | 제품 operation/provider 선택 전 `NOT_SELECTED`; 선택 branch wire adapter 구현 뒤에만 `AVAILABLE_NOT_COMPOSED` |
| retry | 준비됨 + hardening delta | REST 단일 소유, runtime max attempts, Query retry off, logical terminal diagnostics | total elapsed/sleep, 401 single-flight와 protocol별 exact retry/effect certainty 구현 |
| 오류 모델 | 준비됨 | registry-derived `AppFailure`, 공통 `Result`, HTTP normalization과 invalid-kind fixture | 새 failure kind는 registry·copy·telemetry 계약과 함께 추가 |
| Schema·Mapper | reference 준비됨 + governance delta | reference Zod → mapper → domain/application path는 `COMPOSED` | typed codec/mapper proof, semantic fingerprint/provenance, bounded decode와 generated drift gate는 `DESIGNED_NOT_IMPLEMENTED` |
| 인증 연동 | 준비됨/프로젝트 선택 | opaque auth owner와 demo seam 존재 | 인증 방식별 recipe; 기본 token 저장소는 추가하지 않음 |
| 서버 상태 | 준비됨 | reference route의 query/mutation, cancellation, stale, optimistic/conflict/rollback | feature별 query contribution recipe 유지 |
| 서버 상태 | 기본 경로 준비됨 + lifecycle delta | reference query/mutation, cancellation, stale, basic optimistic/conflict/rollback`COMPOSED` | strict bound query policy/key, result/page ceiling, mutation concurrency/CAS rollback은 `DESIGNED_NOT_IMPLEMENTED` |
| 클라이언트 상태 | 준비됨/프로젝트 선택 | local/URL/query/context 소유권, session external store, typed workflow recipe | 실제 cross-page workflow가 생길 때 하나의 store 선택 |
| 범용 global store | 프로젝트 선택 | runtime library 없음, typed facade/fake와 server-state duplication gate | VD-10 조건에 따라 Zustand/Redux Toolkit/state machine 중 하나 선택 |
| 라우팅 | 준비됨 | Data Router, typed runtime map, codec, metadata consumer, bounded chunk recovery | reference feature route와 release E2E로 사용 범위 확장 |
| 라우팅 | 준비됨 | Data Router, typed runtime map, codec, 분리된 route-input provider, metadata consumer, bounded chunk recovery | 새 lazy route도 router 역참조 없이 contribution으로 추가 |
| 앱 셸·반응형 | 준비됨 | native modal Drawer, compact/desktop layout, Escape/link dismiss/focus restore, pseudo reflow와 RTL direction | compact browser matrix 유지 |
| 페이지 템플릿 | 준비됨 | Standard/Collection/Detail/Form/Status와 public design-system entry | feature별 slot 조합 유지 |
| 디자인 토큰 | 준비됨 | primitive/semantic/component CSS, 48-token 자동 계약, dark/forced-colors/reduced-motion | 제품 brand token은 외부 프로젝트에서 확장 |
@@ -83,7 +85,15 @@ P0/P1 acceptance와 P2 recipe 기본값은 `LOCAL_TEMPLATE_READY`다. 다만 실
| 샘플 제거 | 준비됨 | feature/catalog/test 제거 후 type/architecture/registry/test/home/build 9단계 검증 | 새 contribution도 같은 제거 gate에 포함 |
| registry·compatibility 집행 | 준비됨 | 10개 registry type/reference/consumer/orphan, 승인 digest와 actual semantic diff, breaking evidence | public 계약 변경 시 baseline review 유지 |
| 공급망 검사 | 준비됨/프로젝트 선택 | 561개 transitive inventory/integrity/license, actual diff, CycloneDX, local provenance, secret/reproducible build gate | 실제 vulnerability scanner와 signed attestation 없이는 promotion `FAIL_UNVERIFIED` |
| realtime·offline·file 등 | 준비됨/프로젝트 선택 | 12개 opt-in TypeScript port/fake/unavailable, failure/security/bundle/removal gate | 실제 요구·owner 승인 시 해당 recipe만 설치 |
| realtime delivery | 참조 런타임 준비됨/프로젝트 선택 | RT-01~04 공통 event authority, fetch-stream SSE, closed WebSocket, bounded Polling, Web Push window/worker와 handoff/reconnect 조정자는 `AVAILABLE_NOT_COMPOSED`; backend/provider/browser evidence는 없음 | [Realtime events, Web Push, and bounded polling](./realtime-events-web-push-and-bounded-polling.md)의 RT-05 제품 조립·운영 증거를 capability별로 통과 |
| offline·file·browser data | 부분 준비/프로젝트 선택 | opt-in recipe와 gate; capability별 구현·조합·미구현·미선택·platform 제한 상태가 서로 다름 | [Browser data capability completion ledger](./browser-data-capability-completion-ledger.md)의 상태와 work package를 통과한 capability만 설치 |
REST/GraphQL/Connect/gRPC-Web/REST Gateway, Schema/Mapper와 Server State의 상세 current/target 판정은
[API contract, Schema, Mapper와 Server State](./api-contract-schema-mapper-and-server-state.md)를
따른다. Browser Protobuf 축의 선택 기준은
[Protobuf browser transport와 REST Gateway](./protobuf-browser-transport-and-rest-gateway.md)를
따른다. 현재 REST reference 경로의 `COMPOSED` 판정을 GraphQL/Connect/gRPC-Web/
Gateway 또는 REST v2 hardening 완료 증거로 재사용하지 않는다.
## 5. 우선순위별 발견 사항
@@ -91,7 +101,7 @@ P0/P1 acceptance와 P2 recipe 기본값은 `LOCAL_TEMPLATE_READY`다. 다만 실
#### RP-02에서 application 런타임 우회 해결
`src/bootstrap/composition-root.js`가 만든 typed application input API는
`src/bootstrap/composition-root.ts`가 만든 typed application input API는
production `ApplicationProvider`에 주입된다. raw auth, storage, telemetry와
release port는 closure 안에 남고 UI는 session, preference, diagnostics와 runtime
query만 사용한다.
@@ -125,18 +135,19 @@ rollback, conflict resolution과 invalidation을 검증한다. 다른 presentati
#### RP-01에서 TypeScript 검사 도구 안전망 구현
현재 source는 모두 JS/JSX이고 `strict + allowJs + checkJs`를 사용다. 이는 좋은
중간 안전망이지만 다음 도구는 TS migration을 그대로 따라가지 못한다.
초기 source는 JS/JSX `strict + allowJs + checkJs`를 사용다. RP-01 후속
migration으로 현재 product source, tests, Node scripts와 지원 config는 모두
TS/TSX이며 `allowJs`는 꺼져 있다.
- ESLint의 계층·보안 glob은 JS/JSX 중심이다.
- registry scanner `.ts``.tsx`를 찾지 않는다.
- registry governance 경로가 `.js` 확장자로 고정되어 있다.
- tests는 현재 `tsconfig.json` 검사 범위에서 빠진다.
- ESLint의 계층·보안 규칙은 product와 negative fixture의 TS/TSX를 함께 검사한다.
- registry scanner와 governance/baseline은 `.ts``.tsx` 경로를 사용한다.
- app, Node scripts/config, tests는 분리된 strict project로 모두 검사된다.
- architecture gate는 fixture를 포함한 실행 source의 `.js/.jsx/.mjs/.cjs`
재유입을 거절한다.
따라서 파일 확장자를 먼저 바꾸면 새 TS 코드가 일부 자동 검사에서 빠질 수 있다.
TypeScript 전환은
[TypeScript의 JavaScript migration 가이드](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html)
처럼 점진적으로 진행하되, 이 저장소에서는 tooling glob과 CI를 먼저 고쳐야 한다.
전환은 tooling glob과 CI를 먼저 고친 뒤 계약 계층부터 화면·테스트·운영 script
순서로 완료했다. Node 24가 운영 `.ts` script를 직접 실행하고 NodeNext strict
typecheck가 같은 경로를 검증한다.
#### RP-03에서 HTTP 선언과 실행의 차이 해결
@@ -153,7 +164,7 @@ timeout, retry, decoder, mapper 책임을 분리해야 한다. application에는
#### RP-04에서 route registry를 실행 계약으로 전환
platform route 계약과 `src/features/installed-feature-contracts.js`의 직렬화
platform route 계약과 `src/features/installed-feature-contracts.ts`의 직렬화
가능한 contribution을 기준으로
`src/presentation/routes/app-router.tsx`가 Data Router route object와
navigation을 생성한다. `route-runtime.tsx`는 lazy component의 실행 map만
@@ -182,9 +193,11 @@ DTO/schema, mapper, route/API/query contract, query/mutation controller와 page
`test:sample-removal`은 임시 복제본에서 feature source/tests를 삭제하고 installed
contract/runtime/adapter catalog를 빈 목록으로 재생성한다. 그 뒤 typecheck,
architecture, registry, unit/integration, home smoke, build와 fixture ID 잔여
0개를 검사한다. 설치 모드에서는 MSW를 사용한 bootstrap → router → application
→ HTTP → schema → mapper → query cache → page 수직 테스트가 실행된다.
architecture, registry, unit/integration, coverage, source evidence, home smoke,
build와 fixture ID 잔여 0개를 검사한다. feature-owned coverage/evidence policy도
함께 제거되며 generic registry 성공 경로는 공통 unit test가 유지한다. 설치
모드에서는 MSW를 사용한 bootstrap → router → application → HTTP → schema →
mapper → query cache → page 수직 테스트가 실행된다.
#### 비동기·복구 상태의 불변식이 닫혀 있지 않다
@@ -273,11 +286,14 @@ vendor facade, 선택 조건, 실패 정책, 테스트 fixture를 문서로 제
| capability | 대표 기술 | 기본 제공할 경계 | 실제 설치 조건 |
| --- | --- | --- | --- |
| realtime | WebSocket, SSE | subscribe/unsubscribe, reconnect, resume, heartbeat | 서버가 push event를 제공할 때 |
| offline storage | IndexedDB | versioned repository, migration, quota failure | offline read/write가 제품 요구일 때 |
| background/cache | Service Worker, PWA | cache ownership, update, rollback recipe | installable/offline 앱일 때 |
| file transfer | presigned HTTP, multipart | progress, cancel, size/type validation | 업로드·대용량 다운로드가 있을 때 |
| generated API | OpenAPI, GraphQL, gRPC-Web | generated client를 gateway 뒤에 감싸는 규칙 | 서버 계약 형식이 확정됐을 때 |
| foreground realtime | SSE, WebSocket | closed stream/event registry, resume/gap/snapshot, bounded queue와 lifecycle | 측정된 one-way event 또는 duplex interaction 요구와 backend replay/auth owner가 있을 때 |
| background notification | Web Push, persistent notification | permission, subscription register/revoke, Service Worker push/click와 safe route | user-visible background notification과 provider/privacy owner가 승인됐을 때 |
| bounded polling | conditional HTTP query | visible-only single-flight lease, request/time budget와 terminal stop | relaxed freshness 또는 의미가 보존되는 stream fallback이면 충분할 때 |
| structured offline storage | IndexedDB | feature repository, codec/schema 분리, resumable migration, revision/idempotency, blocked/quota recovery | offline record/command가 제품 요구일 때 |
| large local binary | OPFS + IndexedDB journal | immutable chunk, generation/integrity, crash reconciliation, bounded GC | 실제 large local object와 retention owner가 있을 때 |
| public HTTP representation cache | Cache Storage, Service Worker | auth/private 배제, exact match, candidate integrity, update/rollback | install/offline shell 또는 승인된 public cache가 필요할 때 |
| file selection/transfer/delivery | native input, File/Blob, picker, multipart, stream save | opaque file ref, bounded inspection, upload session, handoff/save 구분, object-URL lease | backend 재검증을 포함한 file workflow가 있을 때 |
| generated API | OpenAPI, GraphQL, Connect/gRPC-Web, Protobuf | generated client를 semantic gateway 뒤에 감싸고 transport/gateway 축을 분리하는 규칙 | 서버 계약 형식과 selected operation/provider가 확정됐을 때 |
| feature flag | local/remote flag provider | typed flag key, default, stale behavior | staged rollout가 필요할 때 |
| worker | Web Worker | request/result/cancel protocol | UI thread를 막는 CPU 작업이 있을 때 |
| multi-tab | BroadcastChannel | event versioning, source ID, conflict policy | 탭 간 동기화가 필요할 때 |
@@ -286,18 +302,46 @@ vendor facade, 선택 조건, 실패 정책, 테스트 fixture를 문서로 제
| large data UI | virtualization, data grid | owned component facade | 데이터 규모가 측정 기준을 넘을 때 |
| analytics/error sink | vendor SDK, OpenTelemetry | redaction, consent, sampling adapter | 운영 provider와 정책이 정해졌을 때 |
12개 항목의 현재 상태는 모두 `RECIPE_AVAILABLE / NOT_INSTALLED`다.
catalog의 12개 항목 수는 유지하며 OPFS는 offline recipe의 large-object
sub-capability, Cache Storage는 Service Worker/PWA recipe의 독립 cache policy
sub-capability로 깊이를 보강했다. 현재 상태는 모두
제품 선택 기준으로 `RECIPE_AVAILABLE / NOT_INSTALLED`다. 다만 File/Blob/picker/
download, IndexedDB/OPFS/StorageManager, Cache Storage에는 실제 native API를
호출하는 정책 주입형 reference runtime이 `AVAILABLE_NOT_COMPOSED` 상태로 있으며,
bootstrap과 installed feature에서는 import하지 않는다.
`config/recipes/frontend-capability-recipes.json`이 선택/금지 조건, failure,
cleanup, security/privacy, bundle budget, fallback과 제거 절차의 SSOT이며,
`recipes/frontend-capabilities`에 production-excluded TypeScript port와
fake/unavailable adapter가 있다. 도입 절차는
`docs/architecture/optional-adapter-recipes.md`를 따른다.
fake/unavailable adapter가 있다. file/IndexedDB/OPFS/Cache의 상세한 기술 소유권,
journal, migration, cache activation, test와 운영 복구는
`docs/architecture/browser-file-and-origin-storage.md`와 VD-11을 따른다.
presigned capability, multipart/resume, bounded streaming과 Image CDN은
`docs/architecture/presigned-transfer-and-image-cdn.md`와 VD-12를 따르며, 공통
도입 절차는 `docs/architecture/optional-adapter-recipes.md`를 따른다.
SSE, WebSocket, Web Push와 bounded polling은
`docs/architecture/realtime-events-web-push-and-bounded-polling.md`와 VD-28을
따른다. copyable recipe/fake와 별개로 RT-01~04 reusable source와 deterministic
gate는 `AVAILABLE_NOT_COMPOSED`다. foreground transport, 제품 event registry와
Web Push provider selection은 여전히 `NOT_SELECTED`이며 production bootstrap과
worker에는 조립하지 않는다.
이 capability들을 한꺼번에 "준비됨"으로 표시하지 않는다.
[Browser data capability completion ledger](./browser-data-capability-completion-ledger.md)가
`COMPOSED`, `AVAILABLE_NOT_COMPOSED`, `DESIGNED_NOT_IMPLEMENTED`,
`NOT_SELECTED`, `PLATFORM_LIMITED`를 구분하는 현재 상태의 기준이다. 특히
session/account Query lifecycle, Range resumable download, cross-store quota
orchestration, top-level transfer composition과 Image descriptor HTTP provider는
설계가 승인됐어도 runtime 구현 전에는 `DESIGNED_NOT_IMPLEMENTED`다. Query
persistence, Service Worker offline fetch와 app-managed background
upload/download는 제품이 별도로 선택하기 전에는 `NOT_SELECTED`, 그 cross-browser
guarantee는 `PLATFORM_LIMITED` 상태를 유지한다.
서버의 Redis, MongoDB, PostgreSQL, MinIO를 브라우저가 직접 연결하는 구조는 기본
frontend adapter catalog에 넣지 않는다. 브라우저는 권한 있는 backend API/BFF를
통해 이 자원에 접근해야 한다. 프론트에서 대응되는 변화 지점은 데이터베이스
vendor가 아니라 HTTP/GraphQL/gRPC-Web, realtime, file transfer, cache, storage,
worker, browser capability 같은 프로토콜·런타임 capability다.
vendor가 아니라 HTTP/GraphQL/Connect/gRPC-Web/REST Gateway, realtime, file
transfer, cache, storage, worker, browser capability 같은 프로토콜·런타임
capability다.
### 성능 최적화는 모두 adapter 문제인가
@@ -382,13 +426,15 @@ bootstrap → React TSX → tests 순서로 이동한다.
### retry, API client, logger, token manager, error, validation은 어디에 있는가
- retry: `src/adapters/http/retry-policy.js`, 부분 준비
- API client: `src/adapters/http/client.js`, 부분 준비
- retry: `src/adapters/http/retry-policy.ts`, runtime max-attempt/cleanup 계약까지 구현
- API client: `src/adapters/http/client.ts`, path/search/body projection과
runtime schema/mapper를 사용하며 feature gateway 뒤에서 실행
- logger: `DiagnosticsPort`로 telemetry와 분리해 구현. closed event/level,
allowlist와 bounded/no-op adapter 제공
- token manager: 의도적으로 없음. opaque external auth owner가 credential을 소유
- error: `src/contracts/errors.js`와 HTTP normalization, 부분 준비
- validation: runtime/API Zod는 존재, route/form/domain 분리는 미완성
- error: `src/contracts/errors.ts`의 registry-derived `AppFailure`, 공통
`Result`와 HTTP normalization으로 구현
- validation: runtime/API/route/form Zod와 domain invariant를 소유 경계별로 분리
token manager를 기본으로 추가하지 않는 이유는 token lifecycle이 인증 방식마다
다르고 localStorage token을 일반 해법으로 만들면 보안 위험이 커지기 때문이다.
@@ -468,6 +514,8 @@ data 같은 프로젝트별 외부 작업을 포함하지 않는다.
## 8. 관련 상세 문서
- [API contract, Schema, Mapper와 Server State](./api-contract-schema-mapper-and-server-state.md)
- [Realtime events, Web Push, and bounded polling](./realtime-events-web-push-and-bounded-polling.md)
- [프론트 포트·어댑터와 기능 경계](./frontend-ports-adapters-and-boundaries.md)
- [TypeScript·상태·데이터 흐름](./typescript-state-and-data-flow.md)
- [라우팅·페이지·재사용 패턴](./routing-pages-and-patterns.md)