288 lines
26 KiB
Markdown
288 lines
26 KiB
Markdown
---
|
|
title: branch / feature-frontend-clean-architecture-layering-contract
|
|
source_type: branch-note
|
|
status: raw
|
|
id: BR-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002
|
|
kind: project-work-item
|
|
project: ca-skeleton-frontend-operational-contract
|
|
work_item: WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-002
|
|
inherits: [DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PORT-OWNERSHIP-001@1, DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-COMPOSITION-ROOT-001@1]
|
|
refines: []
|
|
overrides: []
|
|
depends_on: [WI-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-001]
|
|
contract_packet: 1
|
|
branch: feature-frontend-clean-architecture-layering-contract
|
|
parent_branch:
|
|
related_projects: [ca-skeleton-frontend, ca-skeleton]
|
|
governing_docs: [raw/project-notes/ca-skeleton-frontend-operational-contract.md]
|
|
tags: [branch, ca-skeleton, frontend, architecture, application, javascript, clean-architecture]
|
|
created: 2026-07-18
|
|
target_merge:
|
|
status_label: in-progress
|
|
contract_packet_sha256: 1a7d904e9fe76e1aeb6ebd25fea852de7cc888232e96110e832f764d97e518ee
|
|
imports: [FE-OC-004@1, FE-OC-024@1]
|
|
accepts_delegations: [DELEG-FE-003@1, DELEG-FE-005@1]
|
|
|
|
---
|
|
|
|
# branch: feature-frontend-clean-architecture-layering-contract
|
|
|
|
> Layer: `raw/branch-notes/` — 단일 브랜치의 TODO·결정·진행 기록. 머지/종료 후 verified 결과는 `/ingest`로 `wiki/projects/`에 추출한다.
|
|
|
|
<!-- section-id: branch-parent -->
|
|
## 부모 (필수)
|
|
|
|
- [[raw/project-notes/ca-skeleton-frontend-operational-contract]]
|
|
|
|
<!-- GENERATED: branch-contract:start -->
|
|
<!-- section-id: branch-contract-packet -->
|
|
## 브랜치 계약 패킷
|
|
|
|
- **생성 시 프로젝트 개정**: `1`
|
|
- **패킷 스키마**: `contract_packet: 1`
|
|
- **완료 조건**: directory 책임·port owner·allowed import matrix가 문서와 fixture로 고정된다
|
|
|
|
<!-- section-id: inherited-project-decisions -->
|
|
### 상속한 프로젝트 결정
|
|
|
|
| Decision Ref | Project Summary | Branch Application | Source |
|
|
|---|---|---|---|
|
|
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-ARCHITECTURE-001@1` | domain, application, presentation, adapters, bootstrap 책임을 분리한다 | 5-layer directory 책임과 allowed-import matrix에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
|
|
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-PORT-OWNERSHIP-001@1` | output port interface는 application이 소유하고 adapter가 구현한다 | port ownership matrix에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
|
|
| `DEC-CA-SKELETON-FRONTEND-OPERATIONAL-CONTRACT-COMPOSITION-ROOT-001@1` | bootstrap을 단일 composition root로 두고 concrete adapter를 application에 주입한다 | bootstrap boot order와 adapter injection 경계에 적용 | [[raw/project-notes/ca-skeleton-frontend-operational-contract]] |
|
|
|
|
<!-- section-id: branch-local-decisions -->
|
|
### 브랜치 지역 결정
|
|
|
|
> 기존 branch-local 결정은 아래 `## Decision Evidence Map / 결정-근거 매핑`의 D-row가 소유하며 이 packet에서 복제하지 않는다.
|
|
|
|
| Decision ID | Decision | Relation | Supporting Claims | Status |
|
|
|---|---|---|---|---|
|
|
|
|
<!-- section-id: declared-overrides -->
|
|
### 선언한 예외
|
|
|
|
| Override ID | Overrides | Reason | Approval | Status |
|
|
|---|---|---|---|---|
|
|
<!-- GENERATED: branch-contract:end -->
|
|
|
|
<!-- section-id: branch-goal -->
|
|
## 목표
|
|
|
|
이 브랜치는 project-wide 계약 `FE-OC-002`(`domain <- application <- presentation` 의존 방향 + application-owned output port를 MUST 지킴)를 *구현 착수 가능한 상세 명세*로 내린다. 구체적으로 세 가지 불변식을 고정한다: `FE-D009`(domain/application/presentation/adapters/bootstrap 5-layer 책임 분리), `FE-D010`(output port interface는 application 소유, adapter가 구현), `FE-D011`(단일 composition root `bootstrap`이 concrete adapter를 주입). 산출물은 §20 Measurable completion이 요구하는 **directory responsibility + port owner + allowed import matrix** 세 표다. frontend repository가 아직 없으므로 이 브랜치의 모든 항목은 `planned` 등급이며, 착수 시점의 blueprint 근거는 hub §4(§4.2 component responsibility / §4.3 dependency matrix / §4.4 port ownership / §4.5 composition root / §4.6 directory blueprint)다.
|
|
|
|
- 이슈:
|
|
- PR:
|
|
|
|
<!-- section-id: branch-scope -->
|
|
## 범위
|
|
|
|
### 포함 범위
|
|
|
|
- domain / application / presentation / adapters / bootstrap **5-layer 책임 경계** 정의 (hub §4.2) — `FE-D009`
|
|
- **planned directory blueprint** 확정 (hub §4.6) — `FE-D009`
|
|
- **application-owned output port ownership matrix** — port 정의 owner·consumer·I/O·failure vocabulary·"port는 application이 소유한다" 규칙 (hub §4.4) — `FE-D010`
|
|
- **allowed / forbidden import matrix** *규칙 정의* (hub §4.3) — `FE-D009` + `FE-D010`
|
|
- **단일 composition root(bootstrap) injection 원칙 + boot order** (hub §4.5) — `FE-D011`
|
|
- `FE-OC-002`의 minimum evidence인 **dependency rule report** 산출물 정의
|
|
|
|
### 제외 범위
|
|
|
|
> 의도적으로 제외. 인접 계약은 다른 owner 브랜치가 소유하며, 여기서 detail을 쓰지 않고 그 브랜치를 가리킨다 (CLAUDE.md §15.5 R3 `OUT_OF_BRANCH_SCOPE` 방지).
|
|
|
|
- import 규칙의 **실제 lint 강제** (dependency-cruiser / ESLint restricted-import config, allowed/forbidden fixture) → [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]]
|
|
- 각 port의 **concrete method 시그니처 / 구현** → 해당 adapter 브랜치: [[raw/branch-notes/feature-api-client-response-envelope-contract]] (`ResourceQueryPort`/`ResourceCommandPort`), [[raw/branch-notes/feature-server-state-caching-contract]] (`QueryCachePort`), [[raw/branch-notes/feature-frontend-storage-registry-contract]] (`StoragePort`), [[raw/branch-notes/feature-frontend-observability-logging-trace-contract]] (`TelemetryPort`), [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] (`ReleaseInfoPort`)
|
|
- **AuthSessionPort 내부 shape / token lifecycle** → [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] + 외부 Keycloak
|
|
- **runtime config schema / 검증 내용** → [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] (`FE-OC-004`)
|
|
- **boot error shell 렌더링 / reload-loop 방지** → [[raw/branch-notes/feature-frontend-render-recovery-boundary-contract]] (`FE-OC-015`)
|
|
- **toolchain / manifest / checkJs / dev dependency 설치** → [[raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract]] (`FE-OC-003`)
|
|
- **React 사용 결정 자체** (hub `FE-D004`) → [[raw/branch-notes/feature-async-ui-state-contract]]. 본 브랜치는 "선택된 UI framework를 presentation에 가둔다"는 *경계 규칙*만 소유
|
|
- **test gate 종류·fixture·artifact 구조** → [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] (`FE-OC-020`)
|
|
|
|
## 근거 (필수, 최소 1개+)
|
|
|
|
| Source | 정당화하는 결정 |
|
|
|---|---|
|
|
| [[raw/project-notes/ca-skeleton-frontend-operational-contract]] | `FE-OC-002` owner 계약 + `FE-D009`/`FE-D010`/`FE-D011` 결정 register + §4 architecture blueprint의 SSOT (본 브랜치의 모든 planned 경로·규칙 근거) |
|
|
| [[raw/project-notes/ca-skeleton-operational-contract]] | `FE-D009`/`FE-D010`/`FE-D011`의 Clean Architecture **선례** — backend 운영계약의 layer 분리·"application use case는 output port에만 의존"·composition root 단일화(app-bootstrap) 철학을 frontend에 적용 |
|
|
| [[raw/official-docs/react-ui-library-official]] | import matrix의 **React 경계 규칙** — `REACT-UI-C1`(React 앱은 컴포넌트 단위 UI 구성) → React는 presentation 전용, domain/application의 React import 금지 |
|
|
|
|
## TODO
|
|
|
|
- [ ] hub §4.2 component responsibility + §4.6 directory blueprint를 실제 폴더/모듈 책임표로 확정 — 등급: `planned`
|
|
- [ ] hub §4.4 port ownership matrix를 `application/ports` 인터페이스 스텁 목록으로 표현 (정의 owner=application) — 등급: `planned`
|
|
- [ ] hub §4.3 allowed/forbidden import matrix를 machine-readable 규칙 사양으로 문서화 (강제는 enforcement 브랜치) — 등급: `planned`
|
|
- [ ] hub §4.5 composition root boot order(10단계) + adapter injection 지점 명세 — 등급: `planned`
|
|
- [ ] `FE-OC-002` minimum evidence인 dependency rule report 산출물 형식 정의 — 등급: `planned`
|
|
|
|
## 진행 중 메모
|
|
|
|
`/branch-spec`로 채움 (2026-07-19). frontend 코드 부재 → 전 항목 `planned`. 근거 SSOT = frontend hub §4 + backend CA 선례 + `REACT-UI-C1`. 웹 리서치 불필요 (hub가 이미 충분).
|
|
|
|
## 결정 사항
|
|
|
|
> 각 결정의 근거는 아래 Decision Evidence Map과 1:1. 대안과 함께 기록.
|
|
|
|
- 2026-07-19: **5-layer 책임 분리** (domain/application/presentation/adapters/bootstrap) 채택 (`FE-D009`) / 이유: framework-neutral domain 보호 + 의존 방향을 `domain <- application <- presentation` 단방향으로 강제 / 검토한 대안: flat structure, Feature-Sliced Design(FSD) / 근거: backend ca-skeleton 운영계약 CA 철학 [[raw/project-notes/ca-skeleton-operational-contract]]
|
|
- 2026-07-19: **output port interface는 application 소유, adapter가 구현** (`FE-D010`) / 이유: dependency inversion — application이 concrete adapter 이름을 모르게 함 / 검토한 대안: adapter가 인터페이스 소유(전통적 layered) / 근거: project decision + backend port 소유 선례
|
|
- 2026-07-19: **단일 composition root(bootstrap)가 concrete adapter 주입** (`FE-D011`) / 이유: owner ambiguity 제거, 조립 지점 1개로 고정 / 검토한 대안: framework DI container / 근거: project decision + backend app-bootstrap 선례
|
|
- 2026-07-19: **선택된 UI framework(React, hub `FE-D004`)를 presentation에 가둠** (import matrix 규칙) / 이유: React는 UI 구성 관심사이므로 domain/application에 유입 금지 / 검토한 대안: domain/application에 rendering 혼입 / 근거: `REACT-UI-C1`
|
|
- 2026-07-19: **import 규칙 정의=본 브랜치, 강제=enforcement 브랜치 위임** (범위 경계) / 이유: 규칙 정의와 lint 강제 관심사 분리 / 근거: §20 분해표 + §4.3 `Planned enforcement` 컬럼
|
|
|
|
## 결정-근거 매핑
|
|
|
|
> 각 결정과 raw source claim의 연결. `Decision ID`는 이 노트 안에서 안정적으로 유지. `Supporting Claims`는 backtick 포인터(`raw/<cat>/<slug>.md#<CLAIM>`) 또는 hub `FE-D###` / live wikilink.
|
|
|
|
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|
|
|---|---|---|---|---|---|
|
|
| D1 | 5-layer 책임 분리 domain/application/presentation/adapters/bootstrap (`FE-D009` / `FE-OC-002`) | sample slice가 경계의 값을 증명하는 한 default 유지; sample이 불필요한 ceremony임을 증명하거나 FSD fork 승인 시 flat/FSD로 전환 | 프로젝트 결정 `FE-D009`; backend CA 선례 [[raw/project-notes/ca-skeleton-operational-contract]] (domain이 CA 심장, 모든 의존 화살표가 domain으로 수렴) | `project-decision` | 코드 없음 — 5-layer 경계가 실제로 값을 하는지 sample slice(`FE-OC-024`) 전까지 미검증 (over-engineering 위험) |
|
|
| D2 | output port interface는 application 소유, adapter가 구현 (`FE-D010` / `FE-OC-002`) | default 유지; port가 domain invariant 자체를 표현해야 하는 concrete case 발생 시 그 port를 domain으로 이동 | 프로젝트 결정 `FE-D010` (dependency inversion); backend "application use case는 output port에만 의존" 선례 [[raw/project-notes/ca-skeleton-operational-contract]] | `project-decision` | port granularity/개수 미검증 — 잘못된 분할 시 adapter 표면 폭증 |
|
|
| D3 | 단일 composition root(bootstrap)가 concrete adapter 주입 (`FE-D011` / `FE-OC-002`·`FE-OC-004`) | hand-wired DI default 유지; framework DI container 도입 시 재검토 | 프로젝트 결정 `FE-D011`; backend app-bootstrap composition-root 선례 [[raw/project-notes/ca-skeleton-operational-contract]] | `project-decision` | boot order(§4.5 10단계) 결합 — 단계 순서 변경이 여러 adapter 조립에 영향 |
|
|
| D4 | 선택된 UI framework(React)를 presentation에 가둠 — import matrix의 React 금지 row (`FE-OC-002`; framework 선택은 hub `FE-D004`, async-ui 소유) | React가 UI framework인 동안 유지; native/custom-element 또는 다른 framework로 fork(hub `FE-D004` revisit) 시 matrix의 React 금지 심볼만 갱신 | `raw/official-docs/react-ui-library-official.md#REACT-UI-C1`; hub §4.3 dependency matrix | `official-doc` | framework 교체 시 domain/application 격리 규칙 자체는 불변이나 구체 금지 심볼 목록이 바뀜 |
|
|
| D5 | import 규칙 *정의*=본 브랜치, *강제*=enforcement 브랜치 위임 (범위 경계) (`FE-OC-002` contributes) | 규칙 정의(여기)와 lint 강제(enforcement 브랜치) 분리 유지; 두 관심사 병합 승인 시 재검토 | §20 분해표 (`feature-frontend-architecture-enforcement-lint-contract` Primary=—, contributes `FE-OC-002`); hub §4.3 `Planned enforcement` 컬럼 | `project-decision` | 규칙/강제 drift — matrix 변경이 enforcement fixture 미갱신 시 규칙이 무력화 |
|
|
|
|
## 구현 가이드
|
|
|
|
> `planned` blueprint. 경로/책임은 hub §4.2/§4.3/§4.4/§4.5/§4.6에서 도출(근거 있음). frontend 코드는 존재하지 않으므로 전 항목 `planned`. 3-rule (R1 Trace / R2 UNSUPPORTED_IMPL_DECISION / R3 OUT_OF_BRANCH_SCOPE 정제) 준수.
|
|
|
|
### 1. Layer 책임 · directory 책임 map
|
|
|
|
> **Trace**: D1 (`FE-D009`) + `FE-OC-002`; hub §4.2 component responsibility + §4.6 directory blueprint.
|
|
>
|
|
> - **UNSUPPORTED_IMPL_DECISION**: §4.6 blueprint보다 깊은 하위 파일/모듈 명명(예: `domain/models/*` 개별 파일명, `application/use-cases/*` 클래스명)은 hub가 권고하지 않음 → 구현 repository 생성 시 확정. trade-off: blueprint 수준(폴더 책임)까지만 grounded, 그 이하 명명은 첫 sample slice에서 정한다.
|
|
|
|
아래 표에서 본 브랜치가 더하는 것은 **planned path 열** 뿐이다. `Owns`·`Consumes`·`MUST NOT own` 의 owner 는 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §4.2 이므로 여기서 값을 고치지 않는다 — 고쳐야 하면 §4.2 를 고치고 이 표를 따라 갱신한다.
|
|
|
|
| Layer (planned path — 본 브랜치 소유) | Owns (§4.2) | Consumes (§4.2) | MUST NOT own (§4.2) |
|
|
|---|---|---|---|
|
|
| `src/domain/` | framework-neutral model, value semantics, pure policy | standard JavaScript only | React, router, Query, fetch, storage, telemetry |
|
|
| `src/application/` | use case, input/output port, `QueryCachePort` policy, orchestration, view-model contract | domain | concrete adapter, browser global, React component |
|
|
| `src/presentation/` | page/component, user event, view state rendering | application public API | raw API DTO, fetch, storage key, telemetry transport |
|
|
| `src/adapters/http · storage · telemetry · query-cache · auth · release` | application output port 구현, envelope/schema/error·serialization·redaction·key mapping | application port + 해당 browser API | use-case policy, component rendering |
|
|
| `src/bootstrap/` (`main.jsx`, `composition-root.js`, `load-runtime-config.js`) | config load, adapter 생성, DI, React mount | 모든 runtime module | business rule, page-specific orchestration |
|
|
|
|
`src/contracts/` 8개 registry 파일(`routes.js`…`release-tokens.js`)은 각 registry owner 브랜치가 채운다 — 본 브랜치는 *디렉토리 위치*만 blueprint로 고정 (§4.6). registry schema 내용은 governance/owner 브랜치 소유 (R3).
|
|
|
|
### 2. forbidden import matrix (규칙 정의)
|
|
|
|
> **Trace**: D1 (`FE-D009`) + D2 (`FE-D010`) + D4 (`REACT-UI-C1`) + `FE-OC-002`; hub §4.3 dependency matrix.
|
|
>
|
|
> - **UNSUPPORTED_IMPL_DECISION**: `Planned enforcement` 컬럼의 도구(dependency-cruiser + ESLint restricted imports)는 §4.3에 명시되어 grounded이나, *구체 rule config/glob*은 본 브랜치가 정하지 않음 → enforcement 브랜치 소유 (D5, R3). trade-off: 본 표는 "무엇이 금지인가"(machine-readable 규칙)까지만, "어떤 lint 설정으로 잡는가"는 위임.
|
|
|
|
**matrix 본문은 [[raw/project-notes/ca-skeleton-frontend-operational-contract]] §4.3 소유다** — 여기에 옮겨 적지 않는다. 이전 판은 §4.3 의 6행 중 5행만 복제해 `test fixtures` 행과 "**May import 열은 예시(illustrative)이고 MUST NOT 열이 규범(normative)**" 이라는 §4.3 의 경고 문단을 통째로 빠뜨렸고, 그 사본만 읽는 구현자는 §4.3 이 명시적으로 경고한 allow-only 오독(= `FE-D022` 가 의무화한 test stack 이 전부 금지되는 해석)에 그대로 빠진다. `test fixtures` 행의 enforcement 는 [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]] 가 소유한다.
|
|
|
|
Normative 요약: `application -> adapters` concrete import는 MUST NOT; output port는 application이 MUST 소유; adapter는 application을 모름; presentation은 raw envelope를 직접 다루지 않음; bootstrap만 concrete adapter 조립. 이 규칙의 **강제**(fixture pass/fail)는 D5(범위 경계)에 따라 위임한다 → [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]].
|
|
|
|
### 3. Port ownership + composition-root wiring
|
|
|
|
> **Trace**: D2 (`FE-D010`) + D3 (`FE-D011`) + `FE-OC-002`·`FE-OC-004`; hub §4.4 port ownership matrix + §4.5 composition root.
|
|
>
|
|
> - **UNSUPPORTED_IMPL_DECISION**: §4.4의 I/O·failure vocabulary 컬럼 이상의 *concrete method 시그니처*는 각 adapter/port owner 브랜치 소유 (R3) — 본 브랜치는 "port 정의는 application, 구현은 adapter, 조립은 bootstrap"이라는 *ownership 규칙*만 명세. `AuthSessionPort`의 opaque-credential shape는 auth owner가 정함(§4.4 주석).
|
|
|
|
Port 정의 owner = `application` (전부). 구현 위치 = `adapters/*`. 정의된 port(§4.4): `ResourceQueryPort`·`ResourceCommandPort`(→http), `QueryCachePort`(→query-cache), `AuthSessionPort`(→외부 auth), `StoragePort`(→storage), `TelemetryPort`(→telemetry), `ClockPort`(→system), `ReleaseInfoPort`(→release). 각 port의 concrete impl은 해당 owner 브랜치 (Out of scope 참조).
|
|
|
|
Composition root boot order (§4.5, `MUST`): (1) build identity → (2) runtime config fetch → (3) config envelope·schema·compatibility 검증 → (4) release manifest 정합성 → (5) registry snapshot load → (6) auth adapter 주입 → (7) http/storage/telemetry/query-cache adapter 생성 → (8) application facade 생성 → (9) router 생성 → (10) React root mount. **2~4단계 실패 시 product route를 mount하지 않고 boot error shell만 렌더**; telemetry adapter(7) 생성 실패는 console-safe fallback으로 진행. (config 검증 내용=env-config 브랜치, boot error shell 렌더=render-recovery 브랜치 — R3.)
|
|
|
|
### 4. Dependency rule report 산출물
|
|
|
|
> **Trace**: D5 + `FE-OC-002` minimum evidence("dependency rule report", hub §2.1).
|
|
>
|
|
> - **UNSUPPORTED_IMPL_DECISION**: report의 정확한 파일 형식(JSON/HTML)·CI 배치는 미결 → enforcement + test-taxonomy 브랜치와 조율. trade-off: 본 브랜치는 report가 *검증해야 할 명제*(allowed pass / forbidden fail / domain framework-free)만 정의, 형식은 산출 브랜치 소유.
|
|
|
|
report가 assert해야 할 명제: (a) allowed import fixture green, (b) forbidden import fixture red, (c) `domain`의 프레임워크/브라우저 전역 import 0건, (d) concrete adapter 생성이 `bootstrap` 밖에 없음, (e) output port 정의가 `application`에만 존재. 생성 주체·artifact 경로는 enforcement/test-taxonomy 브랜치 (R3, `FE-OC-020`).
|
|
|
|
## 엣지·실패·의존
|
|
|
|
- **실패·엣지 경로**:
|
|
- *import-rule 위반* (한 layer가 금지 방향 import): dependency rule report / architecture fixture가 **red**로 실패 → merge gate 차단. 탐지 mechanism은 enforcement 브랜치 소유(§4.3 Planned enforcement).
|
|
- *composition-root boot 실패* (§4.5 2~4단계: runtime config fetch/검증/release manifest 부정합): product route를 mount하지 않고 **boot error shell만 렌더** (fail-fast). config 검증 내용은 `FE-OC-004`, error shell 렌더는 `FE-OC-015`.
|
|
- *adapter 누락/오주입* (bootstrap이 특정 port impl 미주입): application facade 생성(8단계)이 boot 시점에 throw → fail-fast, boot error shell.
|
|
- *telemetry adapter 생성 실패* (7단계): UI를 실패시키지 않고 console-safe fallback으로 진행(§4.5, `FE-OC-014` best-effort 원칙).
|
|
- *presentation이 raw DTO/fetch/storage 직접 접근*: import matrix 위반 → forbidden fixture가 잡음(enforcement 브랜치).
|
|
- **다른 계약 의존**:
|
|
- [[raw/branch-notes/feature-frontend-project-bootstrap-toolchain-contract]] `FE-OC-003` 에 의존 — manifest·checkJs·dev dependency가 있어야 import graph가 분석·강제 가능 (§20 Dependency).
|
|
- **위임(D5 범위 경계)**: 본 브랜치 import matrix(§2)의 fixture 강제는 [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]] 소유 — 그 계약이 바뀌면 규칙 강제력에 직접 영향.
|
|
- [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] `FE-OC-004` — composition root boot 2~4단계가 소비하는 runtime config 검증·fallback 정책 owner.
|
|
- [[raw/branch-notes/feature-frontend-render-recovery-boundary-contract]] `FE-OC-015` — boot 실패 시 boot error shell 렌더 owner.
|
|
- [[raw/branch-notes/feature-frontend-auth-session-integration-contract]] `FE-OC-010` — `AuthSessionPort` shape/token lifecycle owner (boot 6단계 주입 대상).
|
|
- Port 구현 소비: [[raw/branch-notes/feature-api-client-response-envelope-contract]] `FE-OC-006`, [[raw/branch-notes/feature-server-state-caching-contract]] `FE-OC-012`, [[raw/branch-notes/feature-frontend-storage-registry-contract]] `FE-OC-013`, [[raw/branch-notes/feature-frontend-observability-logging-trace-contract]] `FE-OC-014`, [[raw/branch-notes/feature-frontend-release-cache-rollback-contract]] `FE-OC-016`/`FE-OC-017`.
|
|
- Contributes to: [[raw/branch-notes/feature-async-ui-state-contract]] `FE-OC-011` (application-owned view-model 경계 제공), [[raw/branch-notes/feature-frontend-test-taxonomy-contract]] `FE-OC-020` (architecture fixture를 test 분류의 한 category로 제공).
|
|
|
|
## 검증해야 할 주장
|
|
|
|
| Claim | Why uncertain | How to verify | Status |
|
|
|---|---|---|---|
|
|
| `domain` 모듈이 프레임워크/브라우저 전역을 0건 import한다 | 코드 없음 — 규칙만 존재 | dependency graph snapshot + forbidden-import fixture (enforcement 브랜치 산출) | `needs-confirmation` |
|
|
| `application`이 concrete adapter를 직접 import하지 않는다 | 위와 동일 | allowed/forbidden import fixture (allowed pass / forbidden fail) | `needs-confirmation` |
|
|
| composition root(`bootstrap`)만 concrete adapter를 생성한다 | 위와 동일 | grep + composition-root review — adapter 생성이 bootstrap 밖에 없음 | `needs-confirmation` |
|
|
| output port 정의는 `application`에, 구현은 `adapters/*`에 위치한다 | 위와 동일 | directory 검사 + import graph snapshot | `needs-confirmation` |
|
|
| 5-layer 분리가 sample slice에서 실제로 경계 값을 한다 (over-engineering 아님) | hub `FE-D009` revisit trigger — 미검증 | sample-feature-slice fixture(`FE-OC-024`)로 경계가 값을 증명 / 아니면 재검토 | `needs-confirmation` |
|
|
| 이 import matrix가 dependency-cruiser + ESLint로 실제 강제 가능하다 | 도구 미도입 | enforcement 브랜치의 allowed/forbidden fixture pass/fail (`dependency rule report`) | `needs-confirmation` |
|
|
|
|
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
|
|
|
|
> `/coverage`가 채우는 생성물이며 손으로 유지하지 않는다.
|
|
|
|
| 관심사 | 상태 | owner | 심각도 | 근거 |
|
|
|---|---|---|---|---|
|
|
| TODO — `/coverage` 실행 전 | missing | (없음) | 미평가 | TODO |
|
|
|
|
## 마주친 문제
|
|
|
|
없음 — scaffolding/spec 단계 (frontend 코드 부재).
|
|
|
|
## 묶음 (이 branch에서 파생된 자료)
|
|
|
|
<!-- GENERATED: received-delegations:start -->
|
|
### 수신한 위임
|
|
|
|
| Delegation Ref | From | Concern | Status |
|
|
|---|---|---|---|
|
|
| `DELEG-FE-003@1` | [[raw/branch-notes/feature-frontend-architecture-enforcement-lint-contract]] | `fe.deleg.composition-root-review` | accepted |
|
|
| `DELEG-FE-005@1` | [[raw/branch-notes/feature-api-client-response-envelope-contract]] | `fe.deleg.injectable-random` | accepted |
|
|
<!-- GENERATED: received-delegations:end -->
|
|
|
|
<!-- GENERATED: project-contract-imports:start -->
|
|
## 가져온 프로젝트 계약
|
|
|
|
| Ref | Owner | 요약 | Branch 적용 |
|
|
|---|---|---|---|
|
|
| `FE-OC-004@1` | [[raw/branch-notes/feature-frontend-env-runtime-config-contract]] | build-time, runtime-public, secret config를 MUST 분리하고 boot 전에 runtime config를 검증 | import 참조로 적용 |
|
|
| `FE-OC-024@1` | [[raw/branch-notes/feature-sample-feature-slice-contract-fixture]] | sample은 contract fixture이며 production feature가 의존하면 안 됨 | import 참조로 적용 |
|
|
<!-- GENERATED: project-contract-imports:end -->
|
|
|
|
### Sub-branches (세부 작업)
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
### 오류 기록 (이 branch 작업 중 발생)
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
### 면접 준비 (이 작업에서 나올 수 있는 면접 질문)
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
### 강의 (이 작업을 위해 학습한 강의)
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
### job-posting tie-ins (이 작업에서 파생된 글감)
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
## 관련 일일 노트
|
|
|
|
없음 — scaffolding 단계
|
|
|
|
## 완료 후 정리
|
|
|
|
- PR 링크:
|
|
- 리뷰 메모:
|
|
- 머지 결과 / 배포 환경:
|
|
- **wiki 추출 대상** (verified만, `wiki/projects/`로만 추출):
|
|
- `actually-implemented` 항목:
|
|
- `locally-verified` 항목:
|
|
- `prod-verified` 항목:
|
|
- **추출하지 않을 항목** (planned / documented-only / abandoned):
|