feat: 기능 추가 과정중
This commit is contained in:
@@ -116,7 +116,7 @@ bootstrap은 page별 orchestration이나 업무 규칙을 소유하지 않는다
|
||||
| `src/adapters` | HTTP, auth, storage, cache, telemetry 구현 | outbound adapter |
|
||||
| `src/bootstrap` | runtime config와 구현 조립 | 유일한 composition root |
|
||||
| `src/contracts` | 여러 계층의 registry가 혼재 | 소유 계층으로 분산 |
|
||||
| `src/features/reference-feature` | 완전한 제거 가능 수직 예제 | installed contribution과 8단계 제거 gate 유지 |
|
||||
| `src/features/reference-feature` | 완전한 제거 가능 수직 예제 | installed contribution과 제거 gate 유지 |
|
||||
|
||||
현재 구조가 잘 제공하는 기반은 다음과 같다.
|
||||
|
||||
@@ -132,10 +132,11 @@ bootstrap은 page별 orchestration이나 업무 규칙을 소유하지 않는다
|
||||
|
||||
RP-02 구현으로 다음 경계는 실행 경로에 연결됐다.
|
||||
|
||||
- `src/bootstrap/composition-root.js`가 만든 application을 production
|
||||
- `src/bootstrap/composition-root.ts`가 만든 application을 production
|
||||
`ApplicationProvider`가 실제 React tree에 주입한다.
|
||||
- `createApplication`은 session, preference, diagnostics, runtime query의
|
||||
input API만 반환하며 storage, telemetry, release output port를 숨긴다.
|
||||
- `createApplication`은 session, preference, diagnostics, runtime query와 typed
|
||||
feature input registry만 반환하며 storage, telemetry, release output port를
|
||||
숨긴다.
|
||||
- bootstrap composition 결과는 raw output port를 반환하지 않고
|
||||
application과 React infrastructure만 반환한다.
|
||||
- presentation의 direct fetch/browser storage/concrete adapter/TanStack import와
|
||||
@@ -153,6 +154,16 @@ RP-03 구현으로 HTTP와 server-state 경계도 다음처럼 연결됐다.
|
||||
정리를 테스트한다.
|
||||
- HTTP가 자동 network retry를 소유하고 query/mutation adapter의 vendor retry는
|
||||
비활성화한다.
|
||||
- reference HTTP operation map은 operation ID마다 route ID, request shape와
|
||||
성공 model type을 결합한다. runtime schema와 mapper를 통과한 raw executor는
|
||||
단일 binder에서만 typed executor로 승격되므로 gateway별 응답 cast가 없다.
|
||||
|
||||
위 항목은 reference REST vertical의 `COMPOSED` 증거다. auth owner final-request
|
||||
invariant, auth unavailable fail-close, total deadline, bounded response decoder,
|
||||
typed Schema/Mapper proof, complete pagination과 mutation concurrency 같은
|
||||
production hardening delta는
|
||||
[API contract, Schema, Mapper와 Server State](./api-contract-schema-mapper-and-server-state.md)에
|
||||
별도 `DESIGNED_NOT_IMPLEMENTED`로 기록한다.
|
||||
|
||||
RP-04에서 route 실행 불일치는 닫혔다. route registry와 runtime map은
|
||||
Data Router tree, codec, surface, title, navigation, chunk/release recovery의
|
||||
@@ -163,6 +174,12 @@ contract/presentation은 `src/features/reference-feature`가 소유하고, gener
|
||||
installed catalog만 bootstrap과 router에 노출된다. 제거 gate는 feature와 test를
|
||||
삭제한 복제본에서 전체 P0 경로를 다시 실행한다.
|
||||
|
||||
generic application의 `ApplicationFeatureInputs`는 concrete feature를 import하지
|
||||
않는 open interface다. 각 feature application API가 module augmentation으로
|
||||
자신의 literal ID와 input shape를 기여하고, `features.get(id)`는 ID별 정확한
|
||||
input type을 반환한다. 잘못된 ID/input과 설치 누락은 각각 compile-time negative
|
||||
fixture와 runtime guard로 닫는다.
|
||||
|
||||
RP-06에서 inbound form/page 경계도 실행됐다. `src/presentation/forms`는 Zod
|
||||
presentation schema, controlled field state, error focus, 422 allowlist,
|
||||
pending/deduplication과 dirty navigation을 local facade로 감싼다.
|
||||
@@ -198,7 +215,7 @@ adapter만 교체한다.
|
||||
| Routing과 navigation | inbound | route input/controller | React Router | 필수 |
|
||||
| Form submit과 validation 표시 | inbound | command input port 소비 | React form controller | 필수 |
|
||||
| Server-state query hook | inbound bridge | application input API 소비 | TanStack Query hook | 필수 |
|
||||
| 외부 push event 처리 | inbound | event input port | WebSocket/SSE listener | 선택 |
|
||||
| validated external server event | inbound | event input port | SSE/WebSocket listener, Service Worker push handler | 선택 |
|
||||
| 도메인 API 접근 | outbound | application | Fetch gateway | 필수 |
|
||||
| 인증 session | outbound | application | 외부 auth owner/SDK | 필수 seam |
|
||||
| Credential attachment | outbound | transport 또는 auth integration | auth request decorator | 필수 seam |
|
||||
@@ -396,15 +413,19 @@ Inbound adapter가 해당 type을 application command와 query로 변환한다.
|
||||
### 8.3 예측 가능한 실패를 typed result로 반환한다
|
||||
|
||||
검증 실패, 인증 필요, conflict, network failure처럼 사용자 흐름에
|
||||
포함되는 실패는 `Result<Value, Failure>`로 반환한다. programmer error와
|
||||
포함되는 실패는 `Result<Value, Failure = AppFailure>`로 반환한다. programmer error와
|
||||
불변식 위반을 모두 일반 API 실패로 숨기지는 않는다.
|
||||
|
||||
```ts
|
||||
export type Result<Value, Failure> =
|
||||
export type Result<Value, Failure = AppFailure> =
|
||||
| Readonly<{ ok: true; value: Value }>
|
||||
| Readonly<{ ok: false; error: Failure }>;
|
||||
```
|
||||
|
||||
`AppFailure.kind`는 error registry의 key에서 파생한다. adapter가 받은 외부
|
||||
오류 code는 이 닫힌 vocabulary로 매핑한 뒤 application 경계를 통과하며,
|
||||
transport 문맥의 `ApiFailure`는 같은 type을 가리키는 호환 alias다.
|
||||
|
||||
### 8.4 Input port를 기술별로 합치지 않는다
|
||||
|
||||
`ApplicationService` 한 개에 모든 메서드를 계속 추가하지 않는다.
|
||||
@@ -885,9 +906,11 @@ capability의 기본 정책, port 또는 안전한 no-op 구현과 composition
|
||||
|
||||
| Adapter | 도입 조건 | 기본 상태 |
|
||||
| --- | --- | --- |
|
||||
| WebSocket/SSE | 실시간 server event 필요 | opt-in recipe 제공, 미설치 |
|
||||
| IndexedDB | 큰 offline data 또는 durable queue 필요 | opt-in recipe 제공, 미설치 |
|
||||
| Service Worker/PWA | offline shell과 installability 필요 | opt-in recipe 제공, 미설치 |
|
||||
| SSE/WebSocket/bounded polling | active document의 server event 또는 duplex protocol 필요 | common target `DESIGNED_NOT_IMPLEMENTED`, product `NOT_SELECTED` |
|
||||
| Web Push | inactive browser의 user-visible notification 필요 | target `DESIGNED_NOT_IMPLEMENTED`, product `NOT_SELECTED` |
|
||||
| IndexedDB/OPFS | 큰 offline data, durable queue 또는 large local object 필요 | native reference runtime 제공, 미조립 |
|
||||
| Cache Storage | 승인된 public HTTP representation offline cache 필요 | native reference runtime 제공, 미조립 |
|
||||
| Service Worker/PWA | offline shell과 installability 필요 | lifecycle recipe 제공, 미설치 |
|
||||
| Offline mutation queue | 재연결 후 명령 재처리 필요 | 미설치 recipe |
|
||||
| Feature flag | remote rollout/kill switch 필요 | opt-in recipe 제공, 미설치 |
|
||||
| Translation catalog vendor | 원격 catalog·복수 namespace 운영 필요 | 기본 locale facade 뒤에 미설치 |
|
||||
@@ -896,7 +919,8 @@ capability의 기본 정책, port 또는 안전한 no-op 구현과 composition
|
||||
| OpenTelemetry | 조직 trace 연계 필요 | opt-in recipe 제공, 미설치 |
|
||||
| Web Worker | CPU 작업이 main thread를 막음 | opt-in recipe 제공, 미설치 |
|
||||
| Notification | 사용자 권한 기반 browser notification 필요 | opt-in recipe 제공, 미설치 |
|
||||
| Clipboard/File/Media | 해당 browser capability 필요 | opt-in recipe 제공, 미설치 |
|
||||
| File/Blob/picker/download | 해당 file workflow 필요 | native reference runtime 제공, 미조립 |
|
||||
| Clipboard/Media | 해당 browser capability 필요 | opt-in recipe 제공, 미설치 |
|
||||
| Image CDN adapter | responsive image transform 필요 | 미설치 recipe |
|
||||
| Virtualization | 대량 list rendering이 측정상 병목 | opt-in recipe 제공, 미설치 |
|
||||
| OpenAPI generator | backend 계약에서 client 생성 필요 | opt-in recipe 제공, 미설치 |
|
||||
@@ -906,11 +930,24 @@ capability의 기본 정책, port 또는 안전한 no-op 구현과 composition
|
||||
|
||||
선택 adapter는 “나중에 쓸 수 있으므로” 기본 bundle에 넣지 않는다. 도입
|
||||
조건, 보안 영향, bundle 비용과 제거 방법이 확인된 경우에만 추가한다.
|
||||
현재 구현된 공통 catalog, TypeScript contract/fake와 blocking gate는
|
||||
SSE, WebSocket, Web Push와 bounded polling의 서로 다른 delivery 의미,
|
||||
inbound/outbound 분리, resume·gap·lifecycle과 현재 상태는
|
||||
[Realtime events, Web Push, and bounded polling](./realtime-events-web-push-and-bounded-polling.md)을
|
||||
따른다.
|
||||
Web Push는 subscription/provider/worker delivery를, 별도 Notification 행은
|
||||
permission과 user-visible rendering facade를 뜻한다. bounded polling은 inbound
|
||||
push adapter가 아니라 Query bridge 또는 application orchestrator가 기존 HTTP
|
||||
operation을 schedule하는 policy다.
|
||||
현재 구현된 공통 catalog, TypeScript contract/fake, browser-native reference
|
||||
runtime과 blocking gate는
|
||||
`docs/architecture/optional-adapter-recipes.md`와
|
||||
`config/recipes/frontend-capability-recipes.json`을 따른다. 이 recipe source를
|
||||
production에서 직접 import하는 것은 금지하며 선택한 contract만 application
|
||||
소유 경계로 이동한다.
|
||||
소유 경계로 이동한다. 실제 API를 호출하는 `referenceRuntime`은 catalog에
|
||||
`sourceRoots`가 등록된 browser file/IndexedDB/OPFS/Cache/transfer 계열에만
|
||||
존재한다. realtime target은 아직 `DESIGNED_NOT_IMPLEMENTED`다. 구현된
|
||||
reference runtime도 dataset/schema/codec/query/policy와 제품 owner가 없으면
|
||||
bootstrap에 연결하지 않는다.
|
||||
|
||||
## 19. 새 outbound adapter 추가 recipe
|
||||
|
||||
@@ -1213,8 +1250,8 @@ design-system primitive를 조합하고 controller hook을 통해 application을
|
||||
| Reference feature | full vertical integration과 complete removal |
|
||||
|
||||
TypeScript 전환 후에는 source뿐 아니라 test와 architecture/security
|
||||
fixture도 typecheck 또는 lint 대상이어야 한다. `.ts/.tsx`가 JS 전용 glob을
|
||||
우회하지 않도록 한다.
|
||||
fixture도 typecheck 또는 lint 대상이어야 한다. 모든 실행 fixture를
|
||||
`.ts/.tsx`로 유지해 확장자별 검사 우회를 허용하지 않는다.
|
||||
|
||||
Coverage는 단순 report 생성이 아니라 branch/function/line threshold를
|
||||
blocking gate로 둔다. 수치만 올리기 위한 구현 세부 테스트보다 port
|
||||
@@ -1230,13 +1267,13 @@ contract와 실패 분기를 우선한다.
|
||||
- [ ] `main`은 raw ports 대신 application API를 제공한다.
|
||||
- [ ] `contracts`는 unrestricted 우회 계층이 아니다.
|
||||
- [ ] dependency rule과 문서의 source of truth가 하나다.
|
||||
- [ ] TypeScript와 TSX도 동일한 architecture/security lint를 받는다.
|
||||
- [x] TypeScript와 TSX도 동일한 architecture/security lint를 받는다.
|
||||
|
||||
### 26.2 Runtime composition
|
||||
|
||||
- [ ] runtime timeout/retry 설정이 실제 HTTP transport에 반영된다.
|
||||
- [ ] QueryClient와 feature query bridge가 실제 route에서 동작한다.
|
||||
- [ ] session UI API와 credential attachment가 분리되어 있다.
|
||||
- [x] runtime timeout/retry 설정이 실제 HTTP transport에 반영된다.
|
||||
- [x] QueryClient와 feature query bridge가 실제 route에서 동작한다.
|
||||
- [x] session UI API와 credential attachment가 분리되어 있다.
|
||||
- [x] diagnostics와 telemetry가 HTTP/render/storage/cache failure 경로에
|
||||
연결된다.
|
||||
- [x] `pagehide`에서 bounded telemetry queue를 flush하고 adapter `dispose`가
|
||||
@@ -1245,8 +1282,9 @@ contract와 실패 분기를 우선한다.
|
||||
### 26.3 HTTP와 validation
|
||||
|
||||
- [ ] path, search, body를 각각 검증하고 직렬화한다.
|
||||
- [ ] schema가 반환한 normalized data를 실제 request에 사용한다.
|
||||
- [ ] timeout과 AbortSignal listener가 모든 반환 경로에서 정리된다.
|
||||
- [x] schema가 반환한 normalized data를 실제 request에 사용한다.
|
||||
- [x] 생성된 timeout과 AbortSignal listener가 현재 HTTP attempt의 terminal
|
||||
경로에서 정리된다.
|
||||
- [ ] retry는 runtime cap, idempotency와 `Retry-After`를 따른다.
|
||||
- [ ] raw payload와 credential이 failure나 log에 포함되지 않는다.
|
||||
|
||||
@@ -1256,7 +1294,7 @@ contract와 실패 분기를 우선한다.
|
||||
- [x] params/search schema가 실제 navigation에서 실행된다.
|
||||
- [x] loading/error/chunk/access metadata가 실행 behavior와 연결된다.
|
||||
- [ ] local, URL, server, session, persisted state가 분류 규칙을 따른다.
|
||||
- [ ] server state를 별도 global store에 중복 보관하지 않는다.
|
||||
- [x] reference server state를 별도 global store에 중복 보관하지 않는다.
|
||||
|
||||
### 26.5 Reference feature
|
||||
|
||||
@@ -1268,7 +1306,7 @@ contract와 실패 분기를 우선한다.
|
||||
|
||||
### 26.6 품질
|
||||
|
||||
- [ ] source와 test가 strict TypeScript 검사를 받는다.
|
||||
- [x] source와 test가 strict TypeScript 검사를 받는다.
|
||||
- [ ] React Hooks와 JSX accessibility lint가 blocking이다.
|
||||
- [ ] coverage threshold가 blocking이다.
|
||||
- [ ] MSW integration, component, 3-engine E2E와 axe가 통과한다.
|
||||
@@ -1298,10 +1336,12 @@ contract와 실패 분기를 우선한다.
|
||||
|
||||
### P2: 프로젝트별 선택 capability
|
||||
|
||||
WebSocket/SSE, offline/IndexedDB, Service Worker, feature flag, product
|
||||
SSE/WebSocket, Web Push, bounded polling, offline/IndexedDB, Service Worker, feature flag, product
|
||||
analytics, vendor error reporting, worker, virtualization, OpenAPI generation,
|
||||
global store와 cloud visual-review service는 실제 프로젝트 요구와 측정 결과에
|
||||
따라 추가한다.
|
||||
GraphQL, Connect/gRPC-Web, Protobuf REST Gateway, global store와 cloud
|
||||
visual-review service는 실제 프로젝트 요구와 측정 결과에 따라 추가한다.
|
||||
GraphQL과 browser Protobuf/Gateway의 선택·설치 조건은 VD-26과
|
||||
VD-27/VD-29/VD-30을 따른다.
|
||||
|
||||
P2 adapter를 많이 설치하는 것은 skeleton 완성도의 기준이 아니다.
|
||||
안전한 경계, 도입 recipe, 테스트 계약과 제거 가능성이 준비되어 있는지가
|
||||
|
||||
Reference in New Issue
Block a user