Files
clean-architecture-frontend…/docs/architecture/optional-adapter-recipes.md
T

8.6 KiB

Optional frontend adapter recipes

이 문서는 도메인과 무관한 선택형 frontend capability를 실제 프로젝트에 도입하는 실행 가이드다. 기본 스켈레톤에는 vendor runtime을 설치하지 않는다. RECIPE_AVAILABLE은 계약·fake·failure policy가 준비됐다는 뜻이며 실제 provider, runtime behavior 또는 production readiness를 뜻하지 않는다.

1. 현재 상태와 파일 지도

항목 경로 production 포함
선택/금지/예산 SSOT config/recipes/frontend-capability-recipes.json 정책만
catalog JSON schema schemas/config/frontend-capability-recipes.schema.json 아니오
TypeScript port recipes/frontend-capabilities/contracts.ts 아니오
fake/unavailable recipes/frontend-capabilities/fake-adapters.ts 아니오
contract test tests/recipes/optional-capability-contracts.test.ts 아니오
정적/번들 gate scripts/check-optional-recipes.mjs build 도구
negative fixture scripts/check-optional-recipe-fixtures.mjs 아니오
완전 제거 gate scripts/test-optional-recipe-removal.mjs 아니오

현재 productionRuntimeDependencies는 빈 배열이며 12개 recipe 모두 선택되지 않았다. TypeScript example은 product source가 import할 library가 아니라 선택 시 복사하고 좁힐 출발점이다.

2. 어느 경계에 두는가

capability 성격 port 소유자 adapter 방향 concrete 위치 예
application이 외부 결과를 요청 application outbound src/adapters/<capability>
URL/browser event가 의도를 전달 application input inbound src/presentation/adapters
React rendering behavior만 교체 presentation local facade src/presentation/<capability>
feature 전용 protocol feature application in/out 분리 src/features/<name>/adapters

WebSocket 연결 생성, reconnect와 credential attachment는 outbound다. 수신 JSON 검증과 application input 호출은 inbound다. Service Worker update event, BroadcastChannel event도 같은 원칙을 적용한다. generated DTO와 vendor SDK type은 facade 밖으로 노출하지 않는다.

3. 12개 recipe 선택표

recipe 설치하는 경우 설치하면 안 되는 경우 핵심 fallback
realtime ordered push/resume protocol이 확정됨 polling이 충분하거나 ordering owner 없음 bounded polling/stale UI
offline/IndexedDB durable offline data/queue가 제품 요구 credential 저장, DB 직접 연결, HTTP cache로 충분 online-only + offline state
Service Worker/PWA install/offline shell과 cache owner 승인 update/rollback UX 없음 hosting cache 기반 network app
file transfer progress/cancel/size/type 정책 필요 long-lived credential URL bounded normal request
generated API versioned source와 drift CI가 있음 DTO가 domain/UI로 노출됨 typed request builder + schema
feature flag rollout/kill switch owner와 default 있음 authorization에 사용 typed local default
Web Worker profiler가 main-thread 병목을 증명 단순 network I/O chunked/deferred execution
multi-tab 비민감 event 동기화가 필요 server가 conflict authority focus 시 authoritative refresh
browser permission user gesture 기반 기능 필요 boot 요청, denied UX 없음 manual input/instruction
client workflow cross-page client-only state가 실재 query/server state 복제 URL/local/context/query
large data UI 실측 scale이 budget 초과 pagination으로 충분, a11y 미정 accessible pagination
analytics/error sink provider·consent·retention 승인 arbitrary payload/redaction 우회 bounded local diagnostics

정확한 failure matrix, security/privacy, gzip budget과 제거 순서는 JSON catalog가 SSOT다. 문서와 catalog가 다르면 gate가 검사하는 catalog를 우선 고치고 이 표도 같이 갱신한다.

4. 공통 구현 순서

  1. 문제를 vendor 이름이 아닌 capability와 측정값으로 기록한다.
  2. catalog의 trigger와 forbidden 조건을 모두 검토한다.
  3. project owner, security/privacy reviewer, gzip budget과 재검토 날짜를 VD-10 amendment에 기록한다.
  4. existing URL/local/context/query/application port로 해결되지 않는지 확인한다.
  5. 필요한 contract만 recipes에서 해당 application/presentation 경계로 복사해 실제 payload와 failure union으로 좁힌다.
  6. concrete SDK는 src/adapters/... 또는 local presentation facade adapter에서만 import한다.
  7. composition root가 concrete adapter를 주입한다. page/use case가 constructor를 직접 호출하지 않는다.
  8. fake, unavailable, timeout/cancel, cleanup, malformed input, redaction과 integration test를 작성한다.
  9. runtime config schema, dependency inventory/approval, SBOM, bundle budget, browser support와 runbook을 갱신한다.
  10. 실제 provider integration과 negative behavior가 통과한 뒤에만 catalog 상태를 별도 project catalog에서 INSTALLED로 바꾼다.

5. capability별 필수 검증

Realtime

  • runtime schema로 envelope/version/event ID/sequence/timestamp를 검증한다.
  • reconnect는 exponential backoff 상한, visibility/offline 상태, auth refresh와 resume token expiry를 정의한다.
  • duplicate/out-of-order는 domain use case에 전달하기 전에 정책화한다.
  • route unmount/logout에서 unsubscribe하고 heartbeat timer를 종료한다.

Offline/Service Worker

  • store/cache 이름과 schema는 release와 독립적인 migration version을 가진다.
  • quota, corrupt row, partial migration, downgrade/rollback을 fixture로 만든다.
  • authenticated response와 credential은 기본 cache 대상이 아니다.
  • stale worker loop를 막고 unregister 후 owned cache 삭제가 가능한지 검증한다.

File/generated API

  • upload는 client MIME을 신뢰하지 않고 size/type/server rejection을 모두 다룬다.
  • progress는 unknown total을 허용하며 navigation/unmount에서 AbortSignal로 취소한다.
  • generated code는 facade 뒤 DTO이며 runtime response schema와 contract drift gate를 유지한다.

Flag/worker/multi-tab/browser

  • flag unknown/unavailable/stale에서 명시적 typed fallback을 사용하고 access control로 사용하지 않는다.
  • worker는 task ID/generation/cancel을 사용해 stale result를 폐기하고 crash를 normalized failure로 바꾼다.
  • multi-tab은 source/event/version으로 self-echo와 duplicate를 막고 payload를 비민감 invalidation hint로 제한한다.
  • browser permission은 user gesture에서만 요청하고 denied/dismissed/unsupported를 서로 다른 UX 결과로 처리한다.

Client workflow/large data/analytics

  • workflow store는 server entity/collection을 복제하지 않고 query key나 ID 참조만 보관한다. logout/reset/version mismatch 정책을 테스트한다.
  • virtualization은 profiler와 production-like row count로 정당화하며 keyboard, focus restoration, screen reader와 stale row identity를 검증한다.
  • analytics는 essential diagnostics와 consent-required event를 분리하고 closed event/attribute registry, pre-queue redaction, sampling, bounded queue와 retention을 적용한다.

6. 검증 명령

corepack pnpm check:types:recipes
corepack pnpm test:recipes
corepack pnpm build
corepack pnpm check:optional-recipes
corepack pnpm check:optional-recipe-fixtures
corepack pnpm test:optional-recipe-removal

negative gate는 cleanup 누락, unselected dependency, local adapter 밖 vendor import, credential localStorage/URL/telemetry 경로, workflow store의 server-state 복제와 production source의 recipe import를 거절한다. removal gate는 recipe와 recipe test를 삭제한 임시 사본에서 base typecheck, architecture, test와 build를 실행한다.

7. 제거 체크리스트

  1. 신규 호출과 background 작업을 중지한다.
  2. subscription, worker, channel, media track, observer를 cleanup한다.
  3. persisted store/cache/event queue의 migrate 또는 purge 정책을 실행한다.
  4. composition registration과 runtime config를 제거한다.
  5. concrete adapter, facade/port와 vendor dependency를 제거한다.
  6. dependency baseline, SBOM과 bundle baseline을 갱신한다.
  7. typecheck/test/build, production bundle absence와 도메인 기능 fallback을 검증한다.

provider 장애 시 fake로 바꾸어 production을 PASS 처리하지 않는다. 문서화된 unavailable fallback만 사용하고 provider가 필수인 promotion은 FAIL_UNVERIFIED 또는 blocked 상태로 유지한다.