[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
---
|
||||
id: frontend-million-optimization
|
||||
title: Million.js / React Compiler / Forget — auto optimize
|
||||
category: Coding
|
||||
status: draft
|
||||
source_trust_level: B
|
||||
verification_status: conceptual
|
||||
created_at: 2026-05-09
|
||||
updated_at: 2026-05-09
|
||||
tags: [frontend, react, performance, vibe-coding]
|
||||
tech_stack: { language: "TS / React", applicable_to: ["Frontend"] }
|
||||
applied_in: []
|
||||
aliases: [Million.js, React Compiler, React Forget, automatic memoization, virtual dom optimization]
|
||||
---
|
||||
|
||||
# Million.js / React Compiler
|
||||
|
||||
> React 의 manual `useMemo` / `useCallback` = boilerplate. **React Compiler (Forget) 가 자동 memo. Million.js 가 다른 VDOM**. Modern React 의 큰 변화.
|
||||
|
||||
## 📖 핵심 개념
|
||||
- React Compiler: 자동 memoization (Babel plugin).
|
||||
- Million.js: 다른 VDOM diff (block 식).
|
||||
- Manual memo 불필요.
|
||||
- React 19+ 의 React Compiler stable.
|
||||
|
||||
## 💻 코드 패턴
|
||||
|
||||
### 옛 방식 (manual memo)
|
||||
```tsx
|
||||
const Component = ({ items, onSelect }) => {
|
||||
const sorted = useMemo(() => items.sort(), [items]);
|
||||
const handleClick = useCallback((id) => onSelect(id), [onSelect]);
|
||||
|
||||
return sorted.map(item => <Item key={item.id} onClick={handleClick} />);
|
||||
};
|
||||
```
|
||||
|
||||
→ Boilerplate. 잊으면 re-render.
|
||||
|
||||
### React Compiler (자동)
|
||||
```tsx
|
||||
// 옛 처럼 작성 — compiler 가 자동 memo.
|
||||
const Component = ({ items, onSelect }) => {
|
||||
const sorted = items.sort();
|
||||
const handleClick = (id) => onSelect(id);
|
||||
|
||||
return sorted.map(item => <Item key={item.id} onClick={handleClick} />);
|
||||
};
|
||||
// → Compiler 가 useMemo / useCallback 자동 추가.
|
||||
```
|
||||
|
||||
### React Compiler 설정
|
||||
```js
|
||||
// babel.config.js
|
||||
{
|
||||
plugins: ['babel-plugin-react-compiler'],
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// Vite
|
||||
import reactCompiler from 'babel-plugin-react-compiler';
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
react({
|
||||
babel: { plugins: [['babel-plugin-react-compiler']] },
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### Compiler 의 동작
|
||||
```
|
||||
Input:
|
||||
const Item = ({ name }) => <div>{name}</div>;
|
||||
|
||||
Output (compiled):
|
||||
const Item = (props) => {
|
||||
const $ = _c(2);
|
||||
let t0;
|
||||
if ($[0] !== props.name) {
|
||||
t0 = <div>{props.name}</div>;
|
||||
$[0] = props.name;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
};
|
||||
// → Cache 가 component 안.
|
||||
```
|
||||
|
||||
→ "Memoize all the things" 자동.
|
||||
|
||||
### Compiler 의 한계
|
||||
```
|
||||
Rules of React 위반 = compile X.
|
||||
- Mutation 가 ref 외부.
|
||||
- Closure 가 외부 변수 mutation.
|
||||
- Component 안 effect 가 안 명시.
|
||||
|
||||
→ ESLint rule 가 compile-eligible 검증.
|
||||
```
|
||||
|
||||
```bash
|
||||
npx react-compiler-eslint
|
||||
```
|
||||
|
||||
### Million.js
|
||||
```bash
|
||||
yarn add million
|
||||
```
|
||||
|
||||
```tsx
|
||||
// vite.config.ts
|
||||
import million from 'million/compiler';
|
||||
|
||||
export default {
|
||||
plugins: [million.vite({ auto: true }), react()],
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
// 자동 또는 explicit
|
||||
import { block } from 'million/react';
|
||||
|
||||
const ItemBlock = block(({ name, count }) => (
|
||||
<div>{name}: {count}</div>
|
||||
));
|
||||
|
||||
// 사용
|
||||
<ItemBlock name="x" count={1} />
|
||||
```
|
||||
|
||||
→ Block 안 의 static 부분 = 1번 만. Variable 만 update.
|
||||
|
||||
### Million.js 의 idea
|
||||
```
|
||||
React VDOM:
|
||||
- 매 render = 매 element diff.
|
||||
- 큰 list = 비싼.
|
||||
|
||||
Million block:
|
||||
- Static structure (HTML) + dynamic prop.
|
||||
- 매 render = prop 변경만 적용.
|
||||
|
||||
→ 70-80% 빠름 (specific case).
|
||||
```
|
||||
|
||||
### Auto vs manual block
|
||||
```tsx
|
||||
// Auto (compiler 가 결정)
|
||||
million.vite({ auto: true })
|
||||
|
||||
// Manual
|
||||
const Heavy = block(MyHeavyComponent);
|
||||
```
|
||||
|
||||
→ Auto = simple. Manual = 정밀.
|
||||
|
||||
### When NOT block?
|
||||
```
|
||||
- 동적 children (변하는 structure).
|
||||
- React-specific feature (Suspense, ErrorBoundary inside).
|
||||
- 작은 component (gain 작음).
|
||||
|
||||
→ List item / row / 큰 visual = sweet spot.
|
||||
```
|
||||
|
||||
### React 19 + Compiler
|
||||
```tsx
|
||||
// React 19 + compiler default
|
||||
import { useState } from 'react';
|
||||
|
||||
function Counter() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
// useMemo 없음
|
||||
const expensive = computeExpensive(count);
|
||||
|
||||
// useCallback 없음
|
||||
const handleClick = () => setCount(count + 1);
|
||||
|
||||
return <button onClick={handleClick}>{expensive}</button>;
|
||||
}
|
||||
```
|
||||
|
||||
→ 자동.
|
||||
|
||||
### Performance gain
|
||||
```
|
||||
React 18 (manual memo): baseline.
|
||||
React Compiler: ~10-30% faster (variable).
|
||||
Million block: 70%+ on list-heavy.
|
||||
|
||||
→ Real-world = 10-20% 평균.
|
||||
```
|
||||
|
||||
### Combined
|
||||
```tsx
|
||||
// Compiler + Million
|
||||
const App = () => {
|
||||
const items = useFetch('/items');
|
||||
return <List items={items} />;
|
||||
};
|
||||
|
||||
const List = block(({ items }) => (
|
||||
items.map(item => <Item key={item.id} item={item} />)
|
||||
));
|
||||
```
|
||||
|
||||
### Other optimizers
|
||||
```
|
||||
- Preact (작은 React 비슷)
|
||||
- Solid (no VDOM, 가장 빠름)
|
||||
- Qwik (resumability)
|
||||
- Svelte 5 (signal-based)
|
||||
|
||||
→ React 의 alternative.
|
||||
```
|
||||
|
||||
### Server Component (RSC) 와 함께
|
||||
```
|
||||
RSC = server-render, no client JS.
|
||||
Compiler = client component 의 memo 자동.
|
||||
|
||||
→ 둘 다 사용. RSC 가 큰 win.
|
||||
```
|
||||
|
||||
→ [[React_Server_Components]].
|
||||
|
||||
### Profiling 추천
|
||||
```ts
|
||||
import { Profiler } from 'react';
|
||||
|
||||
<Profiler id="List" onRender={(id, phase, dur) => console.log(id, phase, dur)}>
|
||||
<List />
|
||||
</Profiler>
|
||||
```
|
||||
|
||||
→ Compiler 적용 전후 비교.
|
||||
|
||||
### React Devtools
|
||||
```
|
||||
Profiler tab → flamegraph.
|
||||
Compiled component = "memo" 표시.
|
||||
```
|
||||
|
||||
### useMemo / useCallback 가 obsolete?
|
||||
```
|
||||
React Compiler 후:
|
||||
- useMemo: 거의 X (compiler 자동).
|
||||
- useCallback: 거의 X.
|
||||
- React.memo: 거의 X.
|
||||
|
||||
남은 use case:
|
||||
- Manual control (specific dep)
|
||||
- 레거시 (compiler 옵트아웃)
|
||||
- Compiler 가 못 보는 case (rare)
|
||||
```
|
||||
|
||||
### Bundle size
|
||||
```
|
||||
Million.js: ~7 kB.
|
||||
React Compiler: 0 (build-time).
|
||||
React 19: 약간 작음 보다 18.
|
||||
|
||||
→ Compiler 는 free.
|
||||
```
|
||||
|
||||
### Migration
|
||||
```
|
||||
Existing app:
|
||||
1. ESLint rule 활성 → violation fix.
|
||||
2. React 19 / compiler 옵트인.
|
||||
3. Manual memo 점차 삭제 (선택).
|
||||
4. Million.js 가 큰 list 만.
|
||||
```
|
||||
|
||||
→ Gradual.
|
||||
|
||||
### Future
|
||||
```
|
||||
React Compiler 가 stable (React 19+).
|
||||
Solid / Svelte 5 의 signal 식 = 다른 path.
|
||||
Million.js 가 specific gain.
|
||||
|
||||
→ React 가 자동 optimize 의 길.
|
||||
```
|
||||
|
||||
### Anti-pattern: 미리 memoize
|
||||
```
|
||||
"혹시" useMemo 다 = compiler 가 잘못 보일 수.
|
||||
|
||||
→ Plain code → compiler 가 결정.
|
||||
```
|
||||
|
||||
### Production 의 진짜 답
|
||||
```
|
||||
1. React 19 + Compiler 옵트인.
|
||||
2. ESLint react-compiler 활성.
|
||||
3. Profile → bottleneck 식별.
|
||||
4. Bottleneck 만 Million.js block.
|
||||
|
||||
→ 미리 optimize X.
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준
|
||||
| 상황 | 추천 |
|
||||
|---|---|
|
||||
| New React app | React 19 + Compiler |
|
||||
| Existing | Gradual migrate |
|
||||
| 큰 list | Million.js block + Compiler |
|
||||
| Real-time UI | Solid / Signal (다른 framework) |
|
||||
| Server-heavy | RSC + Compiler |
|
||||
| Microfrontend | Compiler 가 자체 |
|
||||
| Profiler 결과 | Specific block |
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Manual memo + Compiler 둘 다**: redundant (compiler 가 무시).
|
||||
- **모든 거 Million block**: 작은 component 가치 X.
|
||||
- **Compiler 가 fix all 가정**: profile.
|
||||
- **Rules of React 위반**: compile X.
|
||||
- **Premature optimization**: profile 후.
|
||||
- **다른 framework 가 자동 magic**: 모두 trade-off.
|
||||
|
||||
## 🤖 LLM 활용 힌트
|
||||
- React Compiler 가 auto memo.
|
||||
- Manual useMemo / useCallback 가 점차 obsolete.
|
||||
- Million.js 가 list-heavy boost.
|
||||
- Profile 후 specific optimize.
|
||||
|
||||
## 🔗 관련 문서
|
||||
- [[React_useMemo_When_Not_To]]
|
||||
- [[React_useCallback_Reality]]
|
||||
- [[React_Rendering_Optimization]]
|
||||
Reference in New Issue
Block a user