--- 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 => ); }; ``` → 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 => ); }; // → 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 }) =>
{name}
; Output (compiled): const Item = (props) => { const $ = _c(2); let t0; if ($[0] !== props.name) { t0 =
{props.name}
; $[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 }) => (
{name}: {count}
)); // 사용 ``` → 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 ; } ``` → 자동. ### 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 ; }; const List = block(({ items }) => ( items.map(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'; console.log(id, phase, dur)}> ``` → 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]]