39 KiB
title, source_type, status, confidence, tags, related_projects, last_reviewed, diagrams, architecture_review, status_label
| title | source_type | status | confidence | tags | related_projects | last_reviewed | diagrams | architecture_review | status_label | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CA Skeleton Frontend Operational Contract | project-note | draft | unknown |
|
|
2026-07-18 | active |
CA Skeleton Frontend Operational Contract
Layer:
raw/project-notes/(primary, hub) →/ingest후 검증된 사실은wiki/projects/로 추출. 본 문서는 프로젝트의 최상위 hub. 프로젝트 전체 컨텍스트 / 문제 정의 / 시스템 아키텍처 / 핵심 시퀀스가 여기에 집중. 모든 branch / errors / interviews / lectures / job-postings / blog-topics / sources 가 본 문서로 upward link.status_label:active|paused|completed|archived
1. 프로젝트 개요 / Overview
외부인이 1분 안에 "이게 뭐 하는 프로젝트인가" 이해할 수 있어야 함.
- 한 줄 요약: 도메인/비즈니스 로직을 제거한 Clean Architecture 프론트엔드 skeleton. 어떤 화면·기능을 붙여도 (1) 같은 방식으로 백엔드 API 를 호출하고, (2) 같은 방식으로 실패를 분류·표시하고, (3) 같은 계층 의존 규칙을 강제하고, (4) 같은 계약 테스트로 깨짐을 감지하는 React SPA 뼈대. 백엔드 raw/project-notes/ca-skeleton-operational-contract 의 프론트엔드 대응물이며, 개인 학습·포트폴리오·재사용 starter 로 쓴다.
- 기간: 2026-07-18 ~ in-progress (기획 단계 — 코드 미착수,
/branch-spec로 계약별 상세 설계 예정) - 현재 상태:
active - 나의 역할 / Role: 설계자 / 구현자 (개인 프로젝트)
- 저장소 / Repo:
- 메인:
<미생성 — Vite + React + Tailwind SPA 레포 예정>·NO_GROUND_TRUTH: 아직 코드 레포가 없어 본 hub 의 모든 구현 주장은planned등급이다(§9).actually-implemented승격은 레포 생성 후src/grep 으로만. - 부속: —
- 메인:
2. 문제 정의 / Problem
추상화 금지. 구체 시나리오·수치로.
2.1 현재 상태의 문제
- 문제 1: 도메인 없는 React 프로젝트를 새로 시작할 때마다 API 호출 래퍼·에러 분류·로딩/빈/에러 UI 상태·응답 검증을 매번 다르게 재구현한다. 결과적으로 화면마다 실패 처리가 제각각이라, "이 화면은 500 을 어떻게 보여주지?"를 화면 수만큼 되묻게 된다.
- 문제 2: JS(무타입) 환경에서 백엔드 응답 스키마가 바뀌면 컴파일타임이 아니라 런타임에서야 깨짐이 드러난다. 경계에서 검증 계약이 없으면
undefined접근 에러가 UI 트리 깊숙한 곳에서 터져, 원인이 API 계약 변경임을 추적하기 어렵다. - 문제 3: "Clean Architecture"를 표방해도 강제 장치가 없으면 presentation 컴포넌트가 API DTO 를 직접 만지고 의존 방향이 역전된다(백엔드의 ArchUnit 대응물이 프론트엔드엔 부재). 리뷰어의 눈에만 의존하면 시간이 지나며 반드시 새어나간다.
2.2 왜 지금 해결해야 하는가
- 트리거 (왜 지금): 백엔드 raw/project-notes/ca-skeleton-operational-contract 운영 계약을 구축 완료했다. 같은 "도메인 제거 + 운영 계약 우선" 철학을 프론트엔드에 대칭 적용할 시점 — 백엔드가 응답 envelope·error category·trace 를 계약화했으므로 프론트엔드도 그 계약의 소비 규약을 고정해야 짝이 맞는다.
- 비용 (해결 안 했을 때 손실): 계약 없이 화면부터 만들면, 나중에 횡단 관심사(에러 분류·로깅·검증·접근성·성능 예산)를 소급 적용하는 비용이 화면 수에 비례해 폭증한다. 특히 무타입 JS 라 런타임 깨짐이 QA/운영 단계로 밀린다.
- 기회 (해결 시 가치): 도메인 없는 재사용 skeleton 1벌 → 이후 모든 프론트엔드 프로젝트의 출발점 + 면접/포트폴리오에서 "계층·계약·강제 장치를 어떻게 설계했는가"를 증거로 말할 수 있는 자산.
2.3 성공 기준 / Success criteria
측정 가능해야 함. "잘 동작한다" 같은 모호 표현 금지.
아래 임계 수치는 초기 기본값(default) 이며, 각 계약 branch(
/branch-spec)에서 측정·조정한다. "잘 동작한다" 류 추상 표현을 쓰지 않는 것이 목적.
- 기준 1 (계약 관통): 도메인 없는 sample feature slice 화면이
api-client → zod 검증 → error boundary → async 4-state → CA 의존 규칙을 모두 관통하고, 계약 위반 시 실패하는 contract test 가 CI 에서 green. - 기준 2 (의존 규칙 강제): CA 계층 의존 규칙 lint(ESLint boundaries / dependency-cruiser) 위반 0건.
presentation → infrastructure직접 의존 등 역방향 import 발생 시 빌드 실패. - 기준 3 (4-state 강제): 모든 async 화면 표면이
loading / empty / error / success4상태를 렌더. sample slice 에 4상태 각각의 component test(RTL) 존재. - 기준 4 (성능 예산): 프로덕션 초기 JS 번들 < 200KB gzip(default, route-level code splitting 후), web-vitals LCP < 2.5s · CLS < 0.1 · INP < 200ms 임계를 CI 게이트가 검사.
- 기준 5 (재사용성): 새 화면을 만들 때 개발자가 API 에러/로딩/검증을 재구현하지 않고 계약 훅·컴포넌트(
useApiQuery,<AsyncBoundary>,apiClient)를 재사용 — sample slice 복제로 새 화면 골격이 나옴.
3. 시스템 아키텍처 / System architecture
필수 섹션. 아키텍처 다이어그램이 없는 project-note 는 hub 역할을 못 함.
Diagram tool 선택 — 엄격한 분리
| 다이어그램 종류 | 도구 | 이유 |
|---|---|---|
| 시스템 아키텍처 / 컴포넌트 구성도 / 배포 토폴로지 / 데이터 흐름 (정적 구조) | draw.io XML (.drawio 또는 .drawio.svg) |
자유 배치 / 시각적 그룹화 / 신뢰 경계 / 색상 코딩 / Obsidian draw.io 플러그인 native 편집 |
| 시퀀스 다이어그램 | Mermaid sequenceDiagram |
텍스트 기반·git diff 친화, 시간축 표현에 최적 |
| ER 다이어그램 (데이터 모델, 선택) | Mermaid erDiagram |
텍스트 기반·관계 카디널리티 표기 직관적 |
| 작은 결정 트리 / 짧은 플로우차트 | Mermaid flowchart 도 허용 (작은 규모 한정) |
시퀀스가 아닌 단순 분기 |
금지:
- 시스템 아키텍처를 Mermaid
graph TD/graph LR로 작성 — 시각 표현력 부족, draw.io 사용 의무 - 시퀀스 흐름을 draw.io 로 작성 — 시간축 표현 불편, Mermaid 사용 의무
Diagram 컨퍼런스급 표준 (필수 정독)
rules/diagram-standards 에서 컨퍼런스급(Toss SLASH / Kakao if(dev) / Naver DEVIEW 수준) 다이어그램 표준 v2 (minimalist-first) 를 정의한다. 본 template 본문에 별도 기준을 두지 않는다 — 항상
rules/diagram-standards.md를 정독.핵심 원칙: "적을수록 좋다" (Less is more). 정보를 다이어그램에 몰아넣으면 청중이 어디부터 봐야 할지 모른다.
v2 의 요약 (전체는 rules 정독):
- 요소 수 상한 (HARD): Vertex ≤ 10 / Edge ≤ 8 / Callout ≤ 1 / Boundary group ≤ 3 / Legend 항목 ≤ 6 / 색상 ≤ 4
- 박스 라벨 ≤ 2줄, 화살표 라벨 ≤ 5단어
- 80% 회색/흑백 + 강조색 ≤ 2 (color salad 금지)
- Boundary 는 정보 있을 때만 (장식용 boundary 금지)
- Legend 는 표준 컨벤션이면 생략 (점선=외부 / cylinder=DB / 실선=동기 / 점선=비동기 는 legend 불필요)
- Callout 1개 (있을 때만) — 비자명한 함정·결정에만
- 출처 wikilink 는 본문/캡션에, 다이어그램 안에 박지 말 것
- 스케일 어노테이션 (QPS/latency) 은 다이어그램의 질문이 성능 일 때만
- 5초 룰 + 30초 룰 통과
8항 self-check checklist (rules/diagram-standards §14) 를 모두 ✓ 해야 컨퍼런스 발표 가능 수준. 1개라도 미달 → 분할 또는 단순화.
wiki-diagram-revieweragent 가 위 기준으로.drawioXML 을 grep-카운트 후 0~100 점수 부여, ≥95 PASS.
3.1 아키텍처 다이어그램 (draw.io XML)
컴포넌트 구성도. 저장 경로:
raw/diagrams/<project-slug>/하위에.drawio또는.drawio.svg형식으로 저장. Obsidian draw.io 플러그인으로 더블클릭 편집.파일 명명 규약:
architecture-{viewpoint}-YYYY-MM-DD.drawio.svg예:architecture-overview-2026-05-25.drawio.svg,architecture-deployment-2026-05-25.drawio.svg,architecture-data-flow-2026-05-25.drawio.svg임베드 작성 방법: 아래 code block 형식을 참고해 실제 파일명을 채워 wikilink 작성. placeholder 그대로 두지 말 것 — Obsidian이 placeholder를 파일명으로 채택해 root에 orphan 파일을 생성함.
실제 사용 예 (drawio 파일 생성 후 placeholder 부분을 실제 값으로 치환):
![[raw/diagrams/my-project/architecture-overview-2026-05-25.drawio.svg]]
⏳
needs-diagram(DIAGRAM_PENDING_USER) — 아키텍처.drawio는/project-spec가 자동 생성할 수 없다. 아래 대상 파일을 사용자가 직접 작성한 뒤, 백틱을 풀어 활성 임베드(![[...]])로 바꾼다. 그때까지는 inline code span 이라 구조 린터의BROKEN_LINK를 발생시키지 않는다. 이 항목은 readiness 게이트에서 Blocking 이 아니라 Should-fix 로 취급되어 판정이Ready-pending-user가 된다.작성 대상 (권장 viewpoint 2개, 저장 경로
raw/diagrams/ca-skeleton-frontend/):
![[raw/diagrams/ca-skeleton-frontend/architecture-overview-2026-07-18.drawio.svg]]— CA 계층(presentation → application → domain, adapters 는 바깥) + 백엔드 API 신뢰 경계 + cross-cutting(error boundary / observability / config). 화살표는 의존 방향(안쪽을 향함)을 보여준다.![[raw/diagrams/ca-skeleton-frontend/architecture-deployment-2026-07-18.drawio.svg]]— 정적 호스팅(CDN/오브젝트 스토리지) → 브라우저 SPA → 백엔드 API 토폴로지 (서버 런타임 없음).작성 후:
wiki-diagram-reviewer로 ≥95 점 확인(게이트가 판정 못 하는 권고 단계 —rules/project-readiness-gate.mdR2 ≥95 주). 이후 frontmatterdiagrams:배열에 두 파일 등재 +architecture_review:날짜 기입.
다이어그램 작성 요약 (v2 minimalist, 상세는 rules/diagram-standards 정독):
- 컴포넌트 라벨: 시스템 이름 (Bold 1줄) + 핵심 한 줄 (Stack OR 역할, 둘 중 하나만). 절대 ≥3 줄 금지.
예:
**User Service**/Spring Boot 3.4 · :8080(2줄) - 화살표 라벨:
<step?> <verb/protocol> <object>— 5단어 이내 예:① GET /,proxy_pass :8080,Kafka publish user.signed-up - 외부 시스템: 점선 (
#D0D7DE) + fill#F6F8FA. Legend 불필요 (표준 컨벤션) - Boundary: Trust / Network / External — 정보 있을 때만. 모든 컴포넌트를 boundary 1개 안에 넣지 말 것 (정보 0)
- 색상 ≤ 4 — 80% 회색 + 강조 ≤ 2 (blue / orange 한 family씩) + (선택) warning red callout
- Legend 생략 가능 — 점선=외부 / cylinder=DB / 실선=동기 같은 표준 컨벤션이면 legend 불필요. 비표준 색·기호 있을 때만 ≤6 항목 legend.
- 데이터 모델 카디널리티 는 ER 다이어그램 (Mermaid
erDiagram)에서만. 아키텍처 다이어그램의 화살표에1..N같은 cardinality 박지 말 것.
3.2 컴포넌트 책임 분담
다이어그램의 각 컴포넌트가 정확히 무엇을 책임지는지 표로.
컴포넌트 = Clean Architecture 계층. 의존 방향은 항상 바깥→안(presentation → application → domain). adapters 는 domain 이 정의한 port 를 구현해 바깥에서 주입된다. 이 방향을
feature-frontend-architecture-enforcement-lint-contractbranch 가 lint 로 강제한다.
| 컴포넌트 (계층) | 역할 | 기술 스택 | 의존하는 외부 |
|---|---|---|---|
presentation (components / pages) |
UI 렌더 · 사용자 입력 · view-model 만 소비 (raw API DTO 직접 접근 금지) | React 19 + Tailwind | (하위 계층만) |
application (hooks / use-cases) |
화면 로직 · 상태 오케스트레이션 · use-case 훅 | React hooks + TanStack Query | adapters port (인터페이스) |
domain (models / policies) |
도메인 제거 skeleton 이라 최소 — view-model 스키마 · 불변식 · 순수 함수 | 순수 JS + zod schema | 없음 (가장 안쪽, 의존 0) |
adapters/infrastructure (api-client / storage / logger) |
HTTP client · 응답 envelope 파싱 · zod 검증 · storage · 로깅 sink | fetch + zod + TanStack Query | Backend API · 브라우저 storage |
cross-cutting (error-boundary / observability / config) |
에러 경계 · 구조화 로깅 · env config · trace 전파 | React ErrorBoundary + logger | Backend(trace) · error sink |
3.3 외부 의존성 / External dependencies
| 외부 시스템 | 용도 | 통신 방식 | 장애 시 영향 (degrade / fail / fallback) |
|---|---|---|---|
| Backend API | 데이터 read/write (인증 자체는 위임 — 아래) | REST/JSON, structured envelope ({success,data,meta} / {success:false,error}) |
async 4-state 의 error 로 degrade + TanStack Query 가 retryable 만 backoff 재시도 |
| 브라우저 런타임 | 실행 환경 (fetch / history / storage) | Web API | 미지원 API 는 feature-detect + fallback, 앱 셸은 유지 |
| (선택) 에러 트래킹 sink | 관측 (feature-frontend-observability-logging-trace-contract) |
HTTPS, best-effort async | fail 시 콘솔 fallback, 화면 영향 0 |
인증 경계 주의: 토큰 획득/저장/refresh 는 본 skeleton 범위 밖 → raw/project-notes/keycloak-patterns-overview 로 위임. 본 skeleton 은 "이미 인증된 요청" 을 전제로 API 호출 계약만 다룬다(§7 보안 참조).
3.4 배포 다이어그램 / Deployment (선택)
운영 환경 토폴로지가 비자명하면 별도 draw.io.
실제 사용 예 (placeholder 치환 후 사용):
![[raw/diagrams/my-project/architecture-deployment-2026-05-25.drawio.svg]]
4. 핵심 시퀀스 / Key sequences
필수 섹션. 최소 1개의 주요 user flow 를 Mermaid sequence diagram 으로. happy path + 주요 error path 함께.
4.1 인증된 API 호출 + 응답 검증 + 에러 정규화 (핵심 계약 흐름)
시나리오: 이미 인증된 사용자가 화면에 진입해 백엔드 데이터를 읽는다. api-client 가 응답 envelope 을 파싱하고 zod 로 검증한 뒤, 성공/스키마위반/envelope에러를 각각 정규화해 async 4-state 로 표시한다. 이 흐름이 skeleton 의 대다수 계약(api-client · runtime 검증 · error 분류 · async UI state)을 관통한다.
sequenceDiagram
autonumber
actor User
participant UI as Presentation (React)
participant Hook as Application (use-case hook)
participant Q as TanStack Query
participant Client as api-client (adapter)
participant Zod as zod schema
participant API as Backend API
User->>UI: 화면 진입 / 액션
UI->>Hook: useResource()
Hook->>Q: useQuery(key, fetcher)
Q->>Client: GET /api/v1/resource
Client->>API: HTTP GET (traceparent 전파)
alt 200 OK
API-->>Client: {success:true, data, meta}
Client->>Zod: schema.parse(data)
alt 스키마 유효
Zod-->>Client: 검증된 model
Client-->>Q: model
Q-->>Hook: {data, isLoading:false}
Hook-->>UI: view-model
UI-->>User: success 상태 렌더
else 스키마 위반 (SCHEMA_MISMATCH)
Zod-->>Client: ZodError
Client-->>Q: throw ContractError(non-retryable)
Q-->>Hook: {error}
Hook-->>UI: error 상태
UI-->>User: 안전 메시지 (원본/스택 미노출)
end
else 4xx / 5xx (envelope error)
API-->>Client: {success:false, error:{code,category,retryable}}
Client-->>Q: throw ApiError(category)
Q-->>Q: retryable=true 면 exponential backoff 재시도
Q-->>Hook: {error}
Hook-->>UI: error 상태 (category 별 분기)
UI-->>User: error 상태 렌더 (retry 버튼 등)
end
시퀀스 작성 표준 (필수 준수):
autonumber활성화 — 본문에서 "단계 3에서 ..." 처럼 참조 가능actorvsparticipant: 사람은actor, 시스템은participant- 순서: User → Frontend → Backend → External (좌→우)
- 화살표 라벨 명세:
- HTTP:
METHOD /path {body 요약}(예:POST /api/v1/login {email, password}) - 메시징:
event-name {payload 요약}(예:user.signed-up {userId}) - 메서드 호출:
method()(예:validateCredentials())
- HTTP:
- 응답:
-->>(점선 화살표) - alt / opt / loop: 분기·옵션·반복은 명시적 블록
Note over X,Y: 비자명한 동작은 노트로 명시- 에러 경로 1개 이상 필수: happy path 만 그리면 미완성
4.2 앱 부팅 + 런타임 config 검증 (fail-fast)
시나리오: SPA 부팅 시 VITE_* env 를 zod 로 검증한다. 필수 값 누락/형식 오류면 화면을 렌더하지 않고 부팅 에러로 즉시 실패시켜 "잘못된 config 로 반쯤 동작하는 상태" 를 차단한다. (Vite 는 import.meta.env 로만 env 를 노출하고 VITE_ 접두 변수는 번들에 박히므로 secret 은 여기 두지 않는다 — raw/official-docs/vite-build-tool-official.)
sequenceDiagram
autonumber
participant Boot as main.jsx (bootstrap)
participant Cfg as config loader (adapter)
participant Env as import.meta.env
participant Zod as env schema (zod)
participant App as React App
Boot->>Cfg: loadConfig()
Cfg->>Env: read VITE_* 변수
Cfg->>Zod: envSchema.parse(raw)
alt env 유효
Zod-->>Cfg: 검증된 config
Cfg-->>Boot: config
Boot->>App: render(App with config)
else 필수 env 누락 / 형식 오류
Zod-->>Cfg: ZodError
Cfg-->>Boot: throw ConfigError (fail-fast)
Boot-->>Boot: 렌더 중단 + 부팅 에러 화면 (secret 미노출)
end
5. 데이터 모델 / Data model (선택)
핵심 엔터티가 5~10개 이상이면 ER 다이어그램으로. 그 미만이면 글로만.
본 skeleton: 해당 없음 (N/A). 도메인/비즈니스 로직을 제거했으므로 영속 엔터티가 없다. sample feature slice 의 최소 view-model 만 zod schema 로 정의하며(런타임 계약), 관계형 ER 다이어그램은 불요. 도메인 채택 시 각 feature branch 가 자체 view-model schema 를 정의한다.
ER 작성 표준:
- PK / FK 표시 필수
- 관계 카디널리티 기호:
||--||(1:1)||--o{(1:N)}o--o{(M:N)||..o{(identifying vs non-identifying 표현)
- 관계 라벨: 동사로 (예:
places,contains,ordered as) - 핵심 엔터티만 (5~10개 이내). 모든 테이블 그리지 말 것.
6. 기술 결정 / Tech decisions
주요 기술 선택과 이유. 트레이드오프 + 근거 자료 link 필수.
범례:
deferred= 이번/project-spec자동조사 6개 한도 밖으로 미룬 결정 — 근거는 해당 branch 의/branch-spec단계에서 채운다(R3 Blocking 면제). 사용자 결정 은 근거 자료 없이도 확정된 제약이다.
| 결정 영역 | 선택 | 검토한 대안 | 채택 이유 | 트레이드오프 | 근거 자료 |
|---|---|---|---|---|---|
| 언어 | JavaScript (ESM) | TypeScript · JS+JSDoc | 사용자 지정 제약. 진입 장벽·빌드 단순 | ⚠️ 컴파일타임 타입 계약 부재 → 경계 계약을 런타임(zod)이 짊. UNSUPPORTED 아니라 사용자 결정 | (사용자 결정) |
| 빌드/번들 | Vite (client-only SPA) | Next.js · CRA · Remix | 서버 런타임 불필요·백엔드 API 와 분리, native ESM dev server + HMR, import.meta.env 로 env 노출(secret 은 번들 금지) |
SSR/SEO 필요 시 부적합(범위 밖) | [[raw/official-docs/vite-build-tool-official]] |
| UI 라이브러리 | React 19 | Vue · Svelte · SolidJS | 컴포넌트 기반 UI 분해, 생태계·채용시장, 기존 SPA 자산 | 러닝커브·리렌더 관리 | [[raw/official-docs/react-ui-library-official]] |
| 스타일링 | Tailwind CSS | CSS Modules · styled-components · vanilla-extract | utility-first + theme 토큰으로 magic number 제거, 런타임 CSS-in-JS 비용 0 | 클래스 verbosity·초기 학습 | [[raw/official-docs/tailwind-css-utility-first-official]] |
| server-state | TanStack Query | SWR · RTK Query · 수제 | server-state 를 client-state 와 분리, 캐시·동기화·stale 계약을 표준 제공(수제 시 놓침) | 의존성·개념 학습 | [[raw/official-docs/tanstack-query-server-state-official]] |
| 런타임 검증 | zod | yup · valibot · 수제 | 무타입 JS 에서 경계 계약을 .parse() 런타임으로 강제, ZodError 로 실패 신호 |
번들 크기·스키마 유지 | [[raw/official-docs/zod-runtime-schema-validation-official]] |
| 라우팅 | React Router (Declarative Mode) | TanStack Router · wouter | client-only SPA nested route 표준(SSR/framework 모드 불요) | 타입-라우팅은 TanStack 우위; guard/loader 는 별도 계약(branch) | [[raw/official-docs/react-router-official]] |
| client-state | Context / Zustand (경량) | Redux Toolkit · Jotai | server-state 는 Query 담당 → client-state 경량으로 충분 | 규모 증가 시 재검토 | deferred — /branch-spec |
| 테스트 | Vitest + RTL + Playwright | Jest · Cypress | Vite 정합(Vitest), 컴포넌트(RTL)·e2e(Playwright) 계층 분리 | 도구 3종 셋업 | deferred — /branch-spec |
| 아키텍처 패턴 | Clean Architecture (계층 + 의존 규칙) | Feature-Sliced Design · Layered · Atomic | 의존 방향 강제 + 도메인 순수성(백엔드 대칭) | 프론트 적용 시 boilerplate | deferred — branch 단계 wiki-decision-researcher 로 FSD 심층 비교 |
| 계층 강제 도구 | ESLint boundaries / dependency-cruiser | 수동 리뷰 | 의존 규칙 자동 강제(백엔드 ArchUnit 대응) | 규칙 유지보수 | deferred — /branch-spec |
7. 비기능 요구사항 / Non-functional
측정 가능한 비기능 목표. 없으면 명시적으로 "해당 없음".
수치는 초기 default. 각 값의 측정·강제는 대응 계약 branch 가 담당(§8.0).
- 성능: 초기 JS 번들 < 200KB gzip(default) · route-level code splitting · web-vitals LCP < 2.5s / CLS < 0.1 / INP < 200ms 를 CI 게이트가 검사 →
feature-web-vitals-performance-budget-contract(선택 포함). - 가용성: 정적 자산이므로 프론트 자체 다운타임은 CDN 가용성에 종속. 백엔드 장애 시 async 4-state 의
error로 부분 degrade(앱 셸 유지), retryable 요청만 backoff 재시도. - 확장성: 정적 자산 CDN 배포, 상태는 클라이언트 → 수평 확장 무관(서버 인스턴스 없음).
- 보안: 인증 토큰 획득/저장/refresh 는 범위 밖 → raw/project-notes/keycloak-patterns-overview 로 위임. 본 skeleton 은 (1) secret 의 클라이언트 번들 유입 금지(
VITE_*에 secret 금지), (2) XSS 기본 방어(dangerouslySetInnerHTML금지·CSP 권고), (3) 응답 원본/스택/토큰의 화면·로그 노출 금지만 계약화. - 운영 / Observability: 구조화 클라이언트 로깅 + 백엔드로
traceparent전파 + (선택) 에러 트래킹 sink. 토큰·PII 로그 금지 →feature-frontend-observability-logging-trace-contract(선택 포함). - 접근성 / a11y: WCAG 2.1 AA 기본선 — 키보드 네비게이션·focus 관리·ARIA·a11y lint →
feature-accessibility-baseline-contract(선택 포함). - 재해 복구 / DR: 정적 자산 재배포로 복구(RTO 낮음), 클라이언트 무상태(RPO 무관).
- 컴플라이언스: 해당 없음 — 도메인·PII 미수집(skeleton). 도메인 채택 시 재평가.
- i18n: 범위 밖 (deferred) — 이번 skeleton 미포함(사용자 미선택). 후속 프로젝트에서 별도 계약으로.
8.0 Branch 분해 / 실행계획 (Branch decomposition)
/project-spec가 채우는 핸드오프 섹션. 이 hub 에서 깊은 조사로 도출된 자식 branch 의 네이밍과 달성 목표 조건만 적는다. 각 branch 의 결정 내용·메커니즘은 여기 적지 않는다 (SSOT 이중화 방지) — 그건/branch <slug>로 생성 후/branch-spec가 깊게 채운다.작성 규칙:
branch slug는rules/naming-conventions.md§2.1 준수 (prefix 4종feature-/fix-/chore-/experiment-중 하나 + kebab-case, numbered hierarchy 금지).달성 목표 조건은 측정가능해야 함 ("잘 된다" 금지). 그 branch 가 "끝났다"고 말할 수 있는 검증 가능한 결과.우선순위는 실행 순서(P1 먼저). 의존이 있으면의존칸에 선행 branch slug.
| branch slug | 달성 목표 조건 (측정가능) | 우선순위 | 의존 |
|---|---|---|---|
feature-frontend-clean-architecture-layering-contract |
presentation/application/domain/adapters 4계층 디렉터리 + 계층별 허용 import 규칙 문서화, sample import 예시가 규칙과 일치 | P1 | - |
feature-api-client-response-envelope-contract |
fetch 래퍼가 성공/실패 envelope 파싱 + requestId/traceId 전파, 계약 위반 응답 시 정의된 에러 throw (contract test green) | P1 | - |
feature-runtime-schema-validation-contract |
경계(API 응답·form)에서 zod parse 강제, 위반 시 SCHEMA_MISMATCH 로 정규화 (test) | P1 | feature-api-client-response-envelope-contract |
feature-frontend-error-classification-boundary-contract |
에러 category(retryable/non-retryable/auth/validation) 분류 + React ErrorBoundary + 원본/스택 미노출 test | P1 | feature-api-client-response-envelope-contract |
feature-frontend-env-runtime-config-contract |
부팅 시 VITE_ env 를 zod 검증, 필수값 누락 시 fail-fast, secret 번들 미유입 lint (test) | P1 | - |
feature-frontend-architecture-enforcement-lint-contract |
ESLint boundaries/dependency-cruiser 가 역방향 import 시 CI 실패, 위반 0건 리포트 | P1 | feature-frontend-clean-architecture-layering-contract |
feature-async-ui-state-contract |
모든 async 표면이 loading/empty/error/success 4상태 렌더, sample 에 4상태 각각 RTL test | P2 | feature-frontend-error-classification-boundary-contract |
feature-boundary-mapper-viewmodel-contract |
API DTO → view-model 매핑 강제(presentation 이 raw DTO 미접근), 매핑 누락 시 test 실패 | P2 | feature-runtime-schema-validation-contract |
feature-server-state-caching-contract |
TanStack Query query-key 규약·staleTime·invalidation·retry 정책 + 캐시 무효화 시나리오 test | P2 | feature-api-client-response-envelope-contract |
feature-client-state-management-contract |
client-state 경계: server data 를 client store 에 중복 저장 금지, 위반 감지 test | P2 | feature-server-state-caching-contract |
feature-routing-navigation-guard-contract |
route 구조 + guarded route(비인증 redirect)·error/loading route·404 정의, 네비게이션 test | P2 | - |
feature-tailwind-design-token-styling-contract |
theme 토큰(spacing/color scale) 정의 + arbitrary value 금지 lint + 컴포넌트 스타일 경계 규칙 | P2 | - |
feature-frontend-test-taxonomy-contract |
unit/component(RTL)/integration(msw)/e2e(Playwright) 4계층 정의 + 각 계층 예제 test 1개 | P2 | - |
feature-frontend-observability-logging-trace-contract |
구조화 로거 + traceparent 전파 + 토큰/PII redaction, 금지 필드 로그 유입 시 test 실패 | P2 | feature-api-client-response-envelope-contract |
feature-sample-feature-slice-contract-fixture |
도메인 없는 sample slice 가 api-client·zod·error·4-state·CA 계층 모두 관통 + 계약 위반 시 실패 test 세트, 채택 시 제거 가능 표시 | P2 | feature-async-ui-state-contract |
feature-frontend-build-bundle-supply-chain-contract |
Vite 프로덕션 빌드 + code splitting + lockfile 고정 + 번들 분석, 번들 예산 초과 시 CI 실패 | P3 | - |
feature-web-vitals-performance-budget-contract |
LCP/CLS/INP 임계 + 번들 크기 예산을 CI 게이트로 측정, 초과 시 실패 | P3 | feature-frontend-build-bundle-supply-chain-contract |
feature-accessibility-baseline-contract |
WCAG 2.1 AA 기본선 + 키보드 네비·focus·ARIA + a11y lint(axe) CI 게이트, sample slice 통과 | P3 | feature-async-ui-state-contract |
feature-frontend-ci-quality-gates-contract |
lint·test·번들예산·a11y 게이트를 CI 로 통합, 하나라도 실패 시 머지 차단 | P3 | feature-frontend-test-taxonomy-contract |
feature-frontend-api-compatibility-contract |
백엔드 API additive 변경 관대 + breaking 감지(스키마 버전) 정책, 불일치 시 명시적 실패 | P3 | feature-runtime-schema-validation-contract |
채운 뒤:
/branch <slug>→/branch-spec <slug> <근거 URL...>→/depth <slug>순으로 각 branch 를 깊게 작성.
8. Cluster / 묶음 (이 프로젝트에 묶이는 모든 raw 자료)
본 project-note 는 cluster 의 entry point. 모든 branch / errors / interviews / lectures / job-postings / blog-topics / sources 가 여기로 upward link. hub 측에서도 카테고리별 명시.
8.1 Branches (project 의 직접 자식 branch — parent_branch: 비어있음)
project-note 가 직접 가리키는 branch 들. 자식 branch 가 있는 branch 는 자기 Cluster 섹션에서 자식들을 참조하므로 여기에는 등재 안 함.
아직 branch 미생성. §8.0 분해표의 각 slug 를
/branch <slug>→/branch-spec <slug> <근거>→/depth <slug>로 전개하면 여기에 등재한다. P1 6개(layering / api-client / runtime-validation / error-boundary / env-config / arch-enforcement-lint)부터 착수 권장.
8.2 Sources (프로젝트 전체 차원 foundational 조사)
특정 branch 에 묶이지 않는 전체 프로젝트 단위 근거 자료.
[[raw/official-docs/vite-build-tool-official]]— Vite 빌드/dev server +import.meta.envenv·secret 계약 근거[[raw/official-docs/react-ui-library-official]]— React 컴포넌트 모델[[raw/official-docs/tailwind-css-utility-first-official]]— Tailwind utility-first + theme 토큰(magic number 제거)[[raw/official-docs/tanstack-query-server-state-official]]— server-state vs client-state 구분 + 캐시 계약[[raw/official-docs/zod-runtime-schema-validation-official]]— 무타입 JS 런타임 경계 검증(.parse/.safeParse)[[raw/official-docs/react-router-official]]— Declarative Mode nested routing (SSR/framework 모드 아님)
8.3 Errors (branch 외 발생한 환경·운영 이슈)
- (아직 없음 — 구현 착수 후 환경·운영 이슈 발생 시 등재)
8.4 Interview prep (프로젝트 전체 차원 면접 질문)
- (아직 없음)
8.5 Blog topics / job-posting tie-ins
- (아직 없음)
8.6 Derived wiki documents
- (아직 없음 — canonical 승급은 verified 사실 발생 후
/ingest로wiki/projects/에)
9. 검증 등급 / Verification status
본 project-note 의 각 부분이 어느 등급까지 검증되었는지. CLAUDE.md §15 lifecycle 참조.
| 영역 | 등급 | 근거 |
|---|---|---|
| 아키텍처 다이어그램 | planned (needs-diagram) |
§3.1 사용자 작성 예정, 아직 파일 없음 |
| 시퀀스 다이어그램 | documented-only |
§4 Mermaid 2개(설계 흐름), 코드 대응물 없음 |
| 기술 결정 | documented-only |
§6 6개 결정이 official 근거 보유 — 단 결정일 뿐 구현 아님 |
| 비기능 요구사항 | planned |
§7 임계는 목표치, 측정값 없음(코드 미착수) |
9.1 실제 구현 내용 (actually-implemented)
코드에 존재하는 것만. 파일·함수 단위로 구체적으로. 면접에서 "구현했다"고 말해도 되는 부분.
- 없음 — 레포 미생성(
NO_GROUND_TRUTH). 이 항목은 Vite 레포 생성 +src/grep 확인 후에만 채운다.
9.2 로컬/dev 검증 (locally-verified)
로컬 또는 dev 환경에서 동작 확인한 부분. 어떻게 검증했는지(로그/테스트/측정값).
- 없음 (기획 단계).
9.3 운영 검증 (prod-verified)
운영(prod) 환경에서 동작·성능을 확인한 부분. 근거(릴리즈 노트 / 운영 로그 / 모니터링 대시보드 / 인시던트 보고서)를 함께 명시.
- 없음 (기획 단계).
9.4 문서/계획만 존재 (documented-only / planned)
설계 문서에만 있고 아직 구현 안 된 것. 면접에서 "구현했다"고 말하면 안 되는 부분.
- 본 hub 전체가 현재 이 등급 — §1~§8 의 모든 계약·아키텍처·branch 분해는
planned(설계만). 외부에 "구현했다"고 말하면 안 됨. - 아키텍처
.drawio=needs-diagram(§3.1, 사용자 작성 예정). - 각 계약의
actually-implemented승격은 대응 branch 착수 + 코드 커밋 + contract test green 후src/grep 으로 확정.
10. 면접·외부 공개 답변 경계
10.1 자신 있게 답할 수 있는 범위
- 이 skeleton 이 왜 필요한가 — 도메인 없는 운영 계약을 프론트엔드에 대칭 적용한 설계 의도(§1·§2)와 백엔드 skeleton 과의 대응 관계.
- 각 스택의 설계 선택과 트레이드오프(§6) — Vite/React/Tailwind/TanStack Query/zod/React Router 를 왜 골랐는지 + 검토한 대안 + 근거(official 문서).
- CA 계층을 프론트엔드에 적용하고 lint 로 의존 방향을 강제하려는 설계(§3, §8.0), 무타입 JS 에서 zod 로 계약을 런타임 강제하는 이유.
10.2 적당히 답할 수 있는 범위
- 각 계약의 구체 구현 메커니즘 — 아직 branch 설계 단계이므로 "이렇게 설계했다" 수준까지만. "이미 구현했다"로 넘어가면 안 됨.
10.3 답하면 안 되는 / "공식 문서 다시 확인" 해야 하는 범위
- "이 skeleton 을 실제로 구현/운영했다" — 거짓(코드 미착수). "설계·계획했다"만 사실.
- 성능 수치(200KB, LCP/CLS/INP)를 측정 결과처럼 — 전부 목표치.
- 인증 토큰 처리 세부 — 본 skeleton 범위 밖(raw/project-notes/keycloak-patterns-overview).
10.4 과장 금지 지점
외부에 설명할 때 사실보다 부풀려지기 쉬운 표현. 자기 검열용.
- "프로덕션 검증된 프론트엔드 아키텍처" ❌ →
planned. - "번들 200KB 달성 / web-vitals 통과" ❌ → 목표치, 미측정.
- "TanStack Query 로 캐시 최적화 경험" ❌ → 설계 결정일 뿐 구현 경험 아님.
11. Architecture Review Checklist (작성 / 갱신 시 self-check)
본 project-note 가 hub 역할을 제대로 하려면 모두 ✓ 여야 함.
- 한 줄 요약 + 현재 상태 + 나의 역할 채워짐 (§1)
- 측정 가능한 성공 기준 1개 이상 (§2.3)
- 아키텍처 다이어그램 (
.drawio.svg) 1개 이상 첨부 (§3.1) - 다이어그램이 rules/diagram-standards v2 minimalist 통과 —
wiki-diagram-reviewer로 ≥95 점 (vertex ≤ 10 / edge ≤ 8 / callout ≤ 1 / 박스 라벨 ≤ 2줄 / 화살표 라벨 ≤ 5단어 / 80% 회색 + 강조 ≤ 2 / boundary 정보 있을 때만 / 5초 + 30초 룰) - 외부 시스템이 점선 + 회색 fill 로 시각적 구분 (legend 불필요 — 표준 컨벤션)
- 시퀀스 다이어그램 1개 이상 (Mermaid) — happy path + error path 함께 (§4)
- 데이터 모델은 5~10개 이상 엔터티 시에만 ER 그림 (§5)
- 주요 기술 결정 표에 트레이드오프 + 근거 자료 link 명시 (§6)
- 비기능 요구사항이 측정 가능한 수치 (§7)
- Branch 분해표 채워짐 — 각 자식 branch 가 naming-conventions slug + 측정가능 목표조건 (§8.0)
- Cluster 섹션의 project 직접 자식 branch 목록 채워짐 (§8.1)
- 검증 등급이 각 영역별로 매겨짐 (§9)
- 면접 답변 경계 명시 (§10)
- 마지막 architecture review 날짜 frontmatter
architecture_review:에 기록
12. 다이어그램 파일 관리 가이드
draw.io 파일과 Mermaid 코드 모두 본 project-note 와 함께 라이프사이클 관리.
12.1 draw.io (.drawio.svg)
- 저장 위치:
raw/diagrams/<project-slug>/ - 명명:
architecture-{viewpoint}-{YYYY-MM-DD}.drawio.svg- viewpoint 예:
overview,deployment,data-flow,security,network
- viewpoint 예:
- 갱신 시: 새 날짜로 파일 추가 + frontmatter
diagrams:에 모든 활성 다이어그램 나열 - 폐기 시: 파일 삭제하지 말고
diagrams/<project>/archived/하위로 이동 + project-note 에서 link 제거 - Obsidian 임베딩 문법:
![[architecture-overview-2026-05-25.drawio.svg]]
12.2 Mermaid
- 본 문서 본문에 직접. 외부 파일로 분리 안 함.
- 갱신 시: code block 그대로 수정 (git diff 친화적)
- 너무 커지면 (>50줄) 별도 sub-branch 의 branch-note 로 분리하고 본문에서는 요약만
12.3 그림 변경 시 의무
- 아키텍처가 변경되면 본 project-note 의
architecture_review:frontmatter 날짜 갱신 - 변경 사유는 §6 "기술 결정" 표에 한 줄 추가 (예: "2026-06-01: PostgreSQL → Aurora 변경 — 이유: 가용성 SLO 99.99%")
- 폐기된 결정도 표에서 지우지 말고 status 컬럼 추가로 표시 (
active/deprecated/superseded-by-<row>)
13. 관련 개념 / Related concepts
§3~§6 표에 등장하지 않은 보조 개념·자료.
[[raw/project-notes/ca-skeleton-operational-contract]]— 백엔드 대응 skeleton (운영 계약 철학의 원본, 본 프로젝트의 대칭 기준)[[raw/project-notes/keycloak-patterns-overview]]— 인증 토큰 처리 위임처(본 skeleton 범위 밖 경계)[[rules/diagram-standards]]— §3 아키텍처 / §4 시퀀스 다이어그램 컨퍼런스급 표준[[rules/naming-conventions]]— §8.0 branch slug 규칙
14. 다음 단계 / Next steps
- 아키텍처
.drawio2개 작성(§3.1) →wiki-diagram-reviewer≥95 확인 → frontmatterdiagrams:/architecture_review:기입 (readinessReady-pending-user해소) - Vite + React + Tailwind 레포 생성 (§1 저장소 채우기 — 이후
actually-implemented승격 근거) - P1 6개 branch 착수:
/branch feature-frontend-clean-architecture-layering-contract→/branch-spec→/depth(나머지 P1 동일) deferred결정(client-state / 테스트 / 계층강제 도구 / 아키텍처 패턴)을 branch 단계에서wiki-decision-researcher로 대안 심층 조사- frontmatter
tags:확장 검토 — 필요 시 taxonomy 에 L4vite·tanstack-query·zod등재 후 반영