μ± κ°λ°μκ° μΈν°λμ μ μ κ²½ μ μ¨λ λλ μΈμμ λ§λ€κ³ μλ€.
λΈλΌμ°μ λ λ¬Έμ λ·°μ΄μμ μΆλ°νλ€. <a>, <form>, <input> β μ λΆ λ¬Έμλ₯Ό μ½κ³ μ μΆνλ λꡬλ€. κ·Όλ° μ§κΈ μ°λ¦¬κ° λΈλΌμ°μ μμμ λ§λλ 건 Figmaκ³ , Notionμ΄κ³ , Linearλ€. νλ‘ λꡬλ₯Ό λ¬Έμ λ·°μ΄ μμ μ¬λ¦¬κ³ μλ€.
κ·Έλμ λ§€λ² κ°μ λ¬Έμ λ₯Ό κ²ͺλλ€. ν¬μ»€μ€κ° μ΄λ μλμ§ λΈλΌμ°μ μ λ¬Όμ΄λ΄μΌ νκ³ , ν€λ³΄λ λ΄λΉκ²μ΄μ μ μ²μλΆν° μ§μΌ νκ³ , λλκ·Έ, ν΄λ¦½λ³΄λ, λ©ν°μ λ μ , Undo/Redoλ₯Ό μ±λ§λ€ λ€μ λ§λ λ€. μ΄ νλ‘μ νΈλ κ·Έ "λ§€λ²"μ μμ€λ€.
μμλ€. λ€λ§ λ°©ν₯μ΄ λ¬λλ€.
React, Vue, Angular β μ΄κ²λ€μ λ λλ§ μμ§μ΄λ€. "νλ©΄μ λ 그릴κΉ"λ νμμ§λ§, "μ¬μ©μμ μλλ₯Ό μ΄λ»κ² ν΄μν κΉ"λ μ¬μ ν μ± κ°λ°μ λͺ«μ΄λ€.
Radix, Headless UI, Ark UI β λ κ°κΉμ΄ μλλ€. νμ§λ§ μ΄κ²λ€μ κ°λ³ μμ ― λΌμ΄λΈλ¬λ¦¬λ€. Dialog νλ, Listbox νλ. κ°κ°μ μ λμνλλ°, μμ ― κ°μ ν΅μ μ΄ μ λλ€. Listboxμμ μ νν κ±Έ μ Panelμμ μ μ μκ³ , ν¬μ»€μ€κ° Dialogμμ λ€μ Treeλ‘ λμκ° λ μ΄λλ‘ κ°μΌ νλμ§ μ무λ λͺ¨λ₯Έλ€. μ± μ 체λ₯Ό νλμ μμ€ν μΌλ‘ 보λ λ μ΄μ΄κ° μκΈ° λλ¬Έμ΄λ€.
κ·Έλ¦¬κ³ λ κ·Όλ³Έμ μΈ μ΄μ β μ΄κ±Έ λ²μ©μΌλ‘ λ§λ€μ΄μ ν λΉμ¦λμ€ μΈμΌν°λΈκ° μμλ€. Figmaλ Figmaμ μΈν°λμ λ§ μ λλ©΄ λκ³ , Notionμ Notion κ²λ§ μ λλ©΄ λλ€.
AIκ° μ΄κ±Έ λ°κΏ¨λ€. AIκ° μ½λλ₯Ό μ§λ μλμ, μΈν°λμ λ‘μ§μ΄ μ±λ§λ€ λ€λ₯΄λ©΄ AIλ λ§€λ² μλ‘ λ°°μμΌ νλ€. OS λ μ΄μ΄κ° νλ μμΌλ©΄, AIλ κ·Έ κ·μΉ νλλ§ μλ©΄ λλ€. 컀맨λ νλ dispatchνλ©΄ ν¬μ»€μ€, μ λ μ , Undoκ° λ€ λ°λΌμ¨λ€.
κ΄ν κΆμ΄ λ€λ₯΄λ€. μ»΄ν¬λνΈ λΌμ΄λΈλ¬λ¦¬λ **"μ΄ μμ ―μ μ΄λ»κ² λ λλ§ν κΉ"**λ₯Ό νΌλ€. Interactive OSλ **"μ¬μ©μκ° λ νλ €λ κ±΄μ§ μ΄λ»κ² ν΄μν κΉ"**λ₯Ό νΌλ€.
μ¬μ©μκ° Enterλ₯Ό λλ₯Έλ€:
| Radix / Headless UI | Interactive OS | |
|---|---|---|
| λκ° ν΄μ? | ν΄λΉ μ»΄ν¬λνΈμ onKeyDown |
OS 컀λμ 5-Phase Pipeline |
| λ¬΄μ¨ μΌμ΄? | μ»΄ν¬λνΈλ§λ€ λ€λ¦ | OS_ACTIVATE 컀맨λ νλ |
| Dialogμμλ? | Dialog μ»΄ν¬λνΈκ° λ°λ‘ μ²λ¦¬ | κ°μ OS_ACTIVATE |
| Treeμμλ? | Tree μ»΄ν¬λνΈκ° λ°λ‘ μ²λ¦¬ | κ°μ OS_ACTIVATE |
| Kanbanμμλ? | μ§μ ꡬν | κ°μ OS_ACTIVATE |
Enter νλμ μλ―Έκ° μμ€ν
μ 체μμ λμΌνλ€. 컨ν
μ€νΈμ λ°λΌ κ²°κ³Όκ° λ¬λΌμ§ λΏ, ν΄μ κ²½λ‘λ νλλ€. macOSμμ βSκ° μ΄λμλ "μ μ₯"μΈ κ²μ²λΌ.
κ°μ μλ¦¬κ° λ°μ΄ν°μλ μ μ©λλ€:
κΈ°μ‘΄: TodoList β flat CRUD DocsSidebar β tree CRUD Kanban β grouped CRUD
(κ°μ ꡬν) (κ°μ ꡬν) (κ°μ ꡬν)
μ§κΈ: NormalizedCollection β toFlatList (List View)
CRUDλ ν λ² β toVisibleTree (Tree View)
β toGrouped (Kanban View)
CRUD λ‘μ§μ ν λ² μ§λ©΄, 보λ λ°©λ²λ§ κ°μλΌμ΄λ€.
AIνν "μ΄λ° μ± λ§λ€μ΄"λΌκ³ λ§νλ©΄ μ§μ§ λ§λ€μ΄μ§κ² νλ €κ³ .
μ§κΈ AIνν μ±μ μν€λ©΄ λ²νΌ λλ₯΄λ©΄ λμνλ μμ€μ΄ λμ¨λ€. Tab ν€λ‘ μ΄λ μ λκ³ , ν€λ³΄λλ§μΌλ‘ μΈ μ μκ³ , Undo μκ³ , λλκ·Έ μ λλ€. 보μ΄κΈ°λ§ νλ μ±. μΈν°λμ μ΄ μμΌλ μ₯λκ°μ΄μ§ λκ΅¬κ° μλλ€.
AIκ° ν μΌ OSκ° λ³΄μ₯νλ κ²
βββββββββββββ ββββββββββββββ
1. λ°μ΄ν° λͺ¨λΈ μ μ ν€λ³΄λ λ΄λΉκ²μ΄μ
β
2. defineAppμΌλ‘ μ± μ μΈ ν¬μ»€μ€ 볡μ β
3. createCollectionZone CRUD μ°κ²° λ©ν° μ
λ μ
β
4. Zone/ItemμΌλ‘ UI μ μΈ ν΄λ¦½λ³΄λ β
Undo/Redo β
λλκ·Έ μ€ λλ‘ β
μ κ·Όμ± (ARIA) β
AIλ "λ 보μ¬μ€κΉ"λ§ κ²°μ νλ©΄, "μ΄λ»κ² μ‘°μν κΉ"λ OSκ° λ³΄μ₯νλ€. μ΄κ² λλ©΄ AIκ° λ§λ μ±μ΄ μ₯λκ°μ΄ μλλΌ μ§μ§ νλ‘ λκ΅¬κ° λλ€. μ΄κ±΄ 5λ λ€ μ΄μΌκΈ°κ° μλλΌ μ§κΈ μ΄ μ½λλ² μ΄μ€μμ Todo μ±μ΄ μ΄λ―Έ κ·Έλ κ² λμνκ³ μλ€. 980κ° ν μ€νΈκ° μ¦λͺ νλ€.
1-listeners β 2-contexts β 3-commands β 4-effects β 5-hooks β 6-components
ν€λ³΄λ/λ§μ°μ€ μ΄λ²€νΈκ° 리μ€λμμ μΊ‘μ²λκ³ , 컨ν μ€νΈλ₯Ό μ£Όμ λ°μ, 컀맨λλ‘ λ³νλκ³ , μ΄ννΈλ‘ μ€νλλ©°, ν μ ν΅ν΄ UIμ λ°μλλ€. λͺ¨λ μνΈμμ©μ΄ μ΄ λ¨μΌ νμ΄νλΌμΈμ ν΅κ³Όνλ€.
| ν리미ν°λΈ | μν |
|---|---|
| Zone | κ΄ν κΆ μ μ. ARIA role presetμΌλ‘ λμμ μ μΈμ μΌλ‘ κ²°μ |
| Item | ν¬μ»€μ€ κ°λ₯ν 곡κ°μ λ¨μ. Virtual Focus + Roving TabIndex |
| Field | νΈμ§ κ°λ₯ν ν μ€νΈ μμ. IME μμ + 컀맨λ κΈ°λ° μ»€λ°/μ·¨μ |
| Trigger | ν΄λ¦/ν€λ³΄λλ₯Ό 컀맨λλ‘ λ³ν. asChild ν¨ν΄ |
OS_NAVIGATE (κ³΅κ° μ΄λ) Β· OS_TAB (μ ν νμ) Β· OS_SELECT (λ¨μΌ/λ€μ€/λ²μ μ ν) Β· OS_ACTIVATE Β· OS_CHECK Β· OS_DELETE Β· OS_FIELD_START_EDIT Β· OS_FIELD_COMMIT Β· OS_COPY Β· OS_CUT Β· OS_PASTE Β· OS_ESCAPE Β· OS_EXPAND Β· OS_FOCUS Β· OS_STACK_PUSH/POP
Direction (κ³΅κ° μ΄λ) Β· Edge (κ²½κ³ μ²λ¦¬) Β· Tab (μ ν νμ) Β· Target (μ§μ νκ²ν ) Β· Entry (Zone κ° μ§μ μ ) Β· Restore (ν¬μ»€μ€ λ©λͺ¨λ¦¬) Β· Recovery (μμ μ μλ 볡ꡬ)
// μ± μ μ
const TodoApp = defineApp<TodoState>("todo", INITIAL, { history: true });
const listZone = TodoApp.createZone("list");
const { Zone, Item, Field } = listZone.bind({ role: "listbox", onCheck: toggleTodo });
// λ°μ΄ν°: NormalizedCollection { entities, order }
// CRUD: fromEntities (flat) / fromNormalized (tree)
// Views: toFlatList Β· toVisibleTree Β· toGrouped| μ± | μ€λͺ |
|---|---|
| Reference Todo | SaaS μ€νμΌ λ²€μΉλ§ν¬. Kanban 2D Nav, λ©ν°μ λ μ , Undo/Redo, Clipboard, BDD ν μ€νΈ |
| Web Builder | Visual CMS λΉλ. Bento Grid, Block Preset, Seamless Section Navigation |
| Docs Viewer | λ΄μ₯ λ¬Έμ λ·°μ΄. Tree sidebar, λ§ν¬λ€μ΄ λ λλ§ |
// Headless β DOM μμ΄ μ»€λ§¨λ νμ΄νλΌμΈ κ²μ¦
const page = createOsPage();
page.goto("list", { items: ["a", "b", "c"], role: "listbox" });
page.keyboard.press("ArrowDown");
expect(page.focusedItemId()).toBe("b");
// App-level β 격리λ 컀λ λ¨μ ν
μ€νΈ
const app = TodoApp.create();
app.dispatch(toggleTodo({ id: "task-1" }));
expect(app.state.todos["task-1"].completed).toBe(true);Vitest (unit + integration) Β· Vitest Browser (component rendering) Β· Playwright (E2E + APG contract)
- Command Inspector (
Cmd+D) β μ€μκ° μ΄λ²€νΈ νΈλ μ΄μ±, μν κ²μ¬ - Spatial Laboratory β
/focus-showcase,/aria-showcaseμμ 7μΆ νμ λ²€μΉλ§νΉ - APG Contract Tests β W3C WAI-ARIA Authoring Practices μ€μ κ²μ¦
React 19 Β· TypeScript 5.9 Β· Vite 7 Β· Custom Kernel (μμν¨μ + Transaction Log) Β· Tailwind CSS v4 Β· TanStack Router Β· Vitest + Playwright Β· Lucide React Β· Biome
git clone https://github.com/developer-1px/interactive-os.git
npm install
npm run dev # μ± + λ¬Έμ λμ μ€ν
npm test # unit + integration (headless)
npm run test:browser # browser component tests
npm run test:e2e # playwright e2e
npm run typecheck # νμ
체ν¬src/
βββ os/ # OS 컀λ + νμ΄νλΌμΈ
β βββ 1-listeners/ # ν€λ³΄λ/λ§μ°μ€/ν΄λ¦½λ³΄λ μ΄λ²€νΈ 리μ€λ
β βββ 2-contexts/ # DI 컨ν
μ€νΈ (ZoneRegistry λ±)
β βββ 3-commands/ # 13κ° μ»€λ§¨λ λλ©μΈ
β βββ 4-effects/ # Side effects
β βββ 5-hooks/ # React hooks
β βββ 6-components/ # ZIFT ν리미ν°λΈ + Dialog/Toast/QuickPick
β βββ collection/ # NormalizedCollection + collectionView + CRUD
β βββ defineApp.ts # μ± μ μ API
β βββ headless.ts # Headless ν
μ€νΈ μΈνλΌ
βββ apps/
β βββ todo/ # Reference Todo μ±
β βββ builder/ # Web Builder μ±
βββ pages/ # νμ΄μ§ μ»΄ν¬λνΈ + Showcase
βββ docs-viewer/ # λ΄μ₯ λ¬Έμ λ·°μ΄
docs/ # PARA λ°©λ²λ‘ κΈ°λ° λ¬Έμ
βββ 0-inbox/ # μλ‘μ΄ μ μ λ° μμ
μ΄μ
βββ 1-project/ # νμ± νλ‘μ νΈ
βββ 3-resource/ # μ°κ΅¬ λ° λ²€μΉλ§ν¬
βββ archive/ # μλ£λ νλ‘μ νΈ μμΉ΄μ΄λΈ