refactor: 프론트 템플릿 리펙토링

This commit is contained in:
donghyeon-ka
2026-09-18 15:16:58 +09:00
parent c10a709f2c
commit 5cc41467ae
80 changed files with 7227 additions and 4672 deletions
@@ -0,0 +1,127 @@
# Capability consumer experience baseline
Correctness inside a reusable capability is not sufficient. The platform is
also evaluated by how much of that correctness a normal feature developer must
understand.
These measurements are baselines, not score targets. A lower line count is not
automatically better if it hides business semantics or creates a universal
repository abstraction.
## Scenario A — reference REST feature
The existing reference feature is the executable REST consumer.
It covers list/detail/create behavior, mapping, typed operation inputs,
application ports and an optimistic mutation path.
Current source size:
| Feature-owned area | LOC |
| --- | ---: |
| `application/reference-feature-api.ts` | 91 |
| `contracts/reference-mapper.ts` | 109 |
| `adapters/reference-http-gateway.ts` | 65 |
| `adapters/create-reference-feature-input.ts` | 41 |
| Total measured boundary/application source | 306 |
The important boundary metric is not the raw total. It is what those files need
to know about the platform.
Current result:
- HTTP platform imports in the feature adapter layer: 2 files,
- canonical import path used by both:
`src/adapters/http/index.ts`,
- direct imports of `http-execution-v3.ts`, retry scheduler, response reader,
auth admission or effect-certainty internals: 0,
- feature gateway owns transport failure projection: 0,
- feature gateway chooses operation ID, route ID, exact input/value type and
mapper: yes,
- central installed files own feature-specific adapter/runtime wiring: no;
feature-owned contributions are aggregated centrally.
The reusable HTTP capability now owns execution-outcome normalization through
`createFeatureHttpBinding`. A feature may still implement a custom outbound
adapter behind its application port when the reusable contract does not match
its business requirement.
## Scenario B — IndexedDB local draft
An executable consumer probe lives at:
`tests/contract/consumer-experience/indexeddb-local-draft.test.ts`
with the feature-owned fixture:
`tests/contract/consumer-experience/fixtures/local-draft-feature.ts`
The fixture models a small local-draft feature with save/find/remove and
optimistic revision checking.
Measured result:
| Metric | Result |
| --- | ---: |
| feature-owned fixture LOC | 97 |
| platform import statements | 1 |
| native IndexedDB API references | 0 |
| `src/adapters/storage/indexeddb/**` imports | 0 |
| runtime-internal IndexedDB types imported by feature | 0 |
The feature depends only on the public application boundary:
`src/application/ports/browser-file-storage/index.ts`
and specifically `IndexedDbRepositoryPort<LocalDraft, never>`.
The contract test rejects feature source that reaches for
`globalThis.indexedDB`, `IDBFactory`, `IDBDatabase`, `IDBTransaction`,
`IDBObjectStore` or the concrete IndexedDB adapter directory.
## What this does and does not prove
The probe confirms that **feature business code does not need native IndexedDB
knowledge** once an `IndexedDbRepositoryPort` has been composed.
It does not prove that composition of `createIndexedDbRuntime` is cheap.
That constructor still owns substantial infrastructure policy:
- dataset scope and storage policy,
- physical store governance,
- retention/idempotency stores,
- schema migrations,
- codec and query policy,
- lifecycle authority,
- durability, scheduling and observation.
That complexity belongs at the composition/platform boundary, not in the
feature. A new `create...Repository<T>` convenience factory should be added
only when a second real product consumer demonstrates which subset is stable
enough to become a reusable profile. Creating one now would guess at policy and
risk producing a universal storage abstraction.
## Consumer-quality review checklist
For each new product feature, record:
- feature-owned adapter LOC,
- platform glue LOC,
- files changed,
- central catalog edits,
- direct imports from capability-internal modules,
- native browser/network API references,
- duplicated failure/retry/lifecycle policy.
A healthy feature path should look like:
1. domain type and invariant,
2. use case,
3. business port,
4. feature-owned mapper/codec and policy,
5. capability-specific binding,
6. presentation controller/page.
The feature should not need the retry scheduler, abort ownership,
effect-certainty machinery, IndexedDB transaction lifecycle, OPFS journal,
reconnect coordinator or provider process model.