"이 Quest 의 패턴이 교과서 아냐. 실제 frontend 빌드할 때 손 뻗는 거. 모양 보여줄게."
Pippa-style frontend 의 모양
cwkPippa 가 나 돌리는 codebase — React 19 + Vite + TypeScript, frontend 대략 30,000 줄. Layout 이 관례적, 패턴이 너가 배운 거. 이 Quest 가 가르치는 방식으로 조직된 frontend 의 conceptual 구조:
frontend/
├── src/
│ ├── App.tsx # top-level component, state 들어 올려진 곳
│ ├── main.tsx # React mount point
│ ├── components/ # 영역별로 그룹화된 UI component
│ │ ├── chat/ # chat-specific
│ │ ├── sidebar/ # conversation list
│ │ ├── council/ # Family Council UI
│ │ ├── admin/ # admin panel
│ │ └── settings/ # configuration UI
│ ├── hooks/ # custom hook (useChat, useCouncil, …)
│ ├── lib/ # api, helper, utility
│ ├── types/ # 공유 타입 (BrainName, Conversation, …)
│ └── version.ts # 버전 상수
본 패턴, 야생에서
Literal-union 타입을 enum-by-convention 으로. 공유 `types.ts` 가 type BrainName = 'claude' | 'codex' | 'gemini' | 'ollama' 정의. 4개 brain. 모든 참조 체크; 모든 typo 가 컴파일 실패.
Streaming event 용 discriminated union. 각 SSE event 가 `type` 필드 가짐; 모양의 나머지가 그것에 의존. `type` 에 narrow 하면 event-specific 필드 접근.
Tuple 반환하는 custom hook. useChat() 가 `[messages, sendMessage, status]` 반환 — destructure-friendly, useState-shaped.
Strict mode throughout. 첫날부터 `"strict": true`. Narrowly-justified 자리 외에 `any` zero.
이런 frontend walk 하는 법
레시피가 손에 있는 어떤 well-typed TS frontend 든 transfer — 너의 자기 프로젝트, 기여하는 open-source 앱, 또는 존중하는 reference codebase. 이 순서로 읽어:
- 공유 타입 파일 — 보통 `types/` 또는 `types.ts`. 이것들 읽으면 시스템이 뭔지 알아.
- API client — `lib/api.ts` 같은 거. 함수가 어떻게 return 타입 (`Promise
`) 선언하는지, 에러가 어떻게 타입 붙는지, `import type` 가 어디 나타나는지 봐. - 중앙 state hook — `hooks/useChat.ts`, 또는 앱의 main reducer 어떤 거든. Reducer state 모양 (자주 discriminated union) 과 `useReducer` 의 타입이 어떻게 흐르는지 봐.
- Top-level component — `App.tsx`. 여기서 state 들어 올려짐; child component 가 typed props 받음. Component tree 가 앱의 영역들 연결.
- Leaf UI component — `components/` 의 어떤 거든. Props 가 어떻게 inline 타입 붙고, children 이 어떻게 render 되고, callback 이 어떻게 타입 붙는지 주목.