[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -0,0 +1,366 @@
|
||||
---
|
||||
id: frontend-react-compiler-deep
|
||||
title: React Compiler — 자동 memoization deep
|
||||
category: Coding
|
||||
status: draft
|
||||
source_trust_level: B
|
||||
verification_status: conceptual
|
||||
created_at: 2026-05-09
|
||||
updated_at: 2026-05-09
|
||||
tags: [frontend, react, compiler, vibe-coding]
|
||||
tech_stack: { language: "TS / React", applicable_to: ["Frontend"] }
|
||||
applied_in: []
|
||||
aliases: [React Compiler, React Forget, automatic memoization, ESLint react-compiler, useMemoCache]
|
||||
---
|
||||
|
||||
# React Compiler Deep
|
||||
|
||||
> React 19 의 stable feature. **Compiler 가 useMemo / useCallback / React.memo 자동**. 사용자 가 plain code, compiler 가 optimize.
|
||||
|
||||
## 📖 핵심 개념
|
||||
- Babel plugin 가 transform.
|
||||
- 매 component 의 hook 자동 추가.
|
||||
- Rules of React 가 baseline.
|
||||
- ESLint plugin 가 violation 감지.
|
||||
|
||||
## 💻 코드 패턴
|
||||
|
||||
### 옛 (manual)
|
||||
```tsx
|
||||
const sorted = useMemo(() => items.sort(), [items]);
|
||||
const onClick = useCallback((id) => handle(id), [handle]);
|
||||
|
||||
const Item = React.memo(({ item }: ItemProps) => {
|
||||
return <div>{item.name}</div>;
|
||||
});
|
||||
```
|
||||
|
||||
### 새 (compiler)
|
||||
```tsx
|
||||
// 그냥 plain.
|
||||
const sorted = items.sort();
|
||||
const onClick = (id) => handle(id);
|
||||
|
||||
const Item = ({ item }: ItemProps) => {
|
||||
return <div>{item.name}</div>;
|
||||
};
|
||||
|
||||
// Compiler 가 자동 memoize.
|
||||
```
|
||||
|
||||
### Setup (Vite)
|
||||
```ts
|
||||
import reactCompiler from 'babel-plugin-react-compiler';
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
react({
|
||||
babel: { plugins: [['babel-plugin-react-compiler', { target: '19' }]] },
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### Setup (Next.js 15+)
|
||||
```js
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
experimental: {
|
||||
reactCompiler: true,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### ESLint
|
||||
```bash
|
||||
yarn add -D eslint-plugin-react-compiler
|
||||
|
||||
# .eslintrc.json
|
||||
{
|
||||
"plugins": ["react-compiler"],
|
||||
"rules": { "react-compiler/react-compiler": "error" }
|
||||
}
|
||||
```
|
||||
|
||||
→ Violation 가 compile 못 함.
|
||||
|
||||
### Output (compiled)
|
||||
```tsx
|
||||
// Input
|
||||
function Counter({ count, onIncrement }) {
|
||||
return <button onClick={onIncrement}>{count}</button>;
|
||||
}
|
||||
|
||||
// Output (대략)
|
||||
function Counter(props) {
|
||||
const $ = _c(2);
|
||||
let t0;
|
||||
if ($[0] !== props.count || $[1] !== props.onIncrement) {
|
||||
t0 = <button onClick={props.onIncrement}>{props.count}</button>;
|
||||
$[0] = props.count;
|
||||
$[1] = props.onIncrement;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
```
|
||||
|
||||
→ `_c` = useMemoCache (자동 cache).
|
||||
|
||||
### Rules of React (compile baseline)
|
||||
```ts
|
||||
// ❌ Component 안 mutation 외부
|
||||
let counter = 0;
|
||||
function Counter() {
|
||||
counter++; // 외부 mutation
|
||||
return <div>{counter}</div>;
|
||||
}
|
||||
|
||||
// ✅ State / ref 사용
|
||||
function Counter() {
|
||||
const [count, setCount] = useState(0);
|
||||
return <div>{count}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### Mutation 안 됨
|
||||
```ts
|
||||
// ❌ Props mutation
|
||||
function Item({ item }) {
|
||||
item.name = item.name.toUpperCase(); // mutation
|
||||
return <div>{item.name}</div>;
|
||||
}
|
||||
|
||||
// ✅ 새 object
|
||||
function Item({ item }) {
|
||||
const upper = item.name.toUpperCase();
|
||||
return <div>{upper}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### Effect dependency
|
||||
```tsx
|
||||
// Compiler 가 useEffect 도 optimize.
|
||||
useEffect(() => {
|
||||
doSomething(value);
|
||||
}, [value]);
|
||||
|
||||
// → 자동 dependency tracking (compiler 가 보장).
|
||||
```
|
||||
|
||||
→ Linter 가 dep 체크 가 unnecessary 가 됨.
|
||||
|
||||
### useMemo / useCallback 가 obsolete?
|
||||
```
|
||||
대부분: yes.
|
||||
- Compiler 가 자동.
|
||||
- 더 정확.
|
||||
|
||||
남은 use case:
|
||||
- Manual fine-grained control.
|
||||
- Compiler 옵트아웃 file.
|
||||
- 매우 expensive computation (compiler 가 보장 X).
|
||||
```
|
||||
|
||||
### React.memo 가 obsolete?
|
||||
```
|
||||
대부분: yes.
|
||||
- Compiler 가 component 자동 memo.
|
||||
|
||||
남은:
|
||||
- 외부 lib component (compiler 가 못 보는).
|
||||
- 정밀 prop comparison.
|
||||
```
|
||||
|
||||
### "use no memo" (옵트아웃)
|
||||
```tsx
|
||||
'use no memo';
|
||||
|
||||
function Component() {
|
||||
// Compiler 가 optimize X.
|
||||
}
|
||||
```
|
||||
|
||||
→ 안 optimize 의 file.
|
||||
|
||||
### Performance gain
|
||||
```
|
||||
Real-world:
|
||||
- 10-30% 빠름 (개발자 실수 fix).
|
||||
- 큰 list = 더 큰.
|
||||
- 작은 component = 작은.
|
||||
|
||||
→ "Manual perfect 한 코드" = gain 0.
|
||||
"Manual 부족 한 코드" = 큰 gain.
|
||||
```
|
||||
|
||||
### Side effect detection
|
||||
```tsx
|
||||
function Component() {
|
||||
// ❌ Render 중 side effect
|
||||
localStorage.setItem('x', 'y');
|
||||
|
||||
return <div />;
|
||||
}
|
||||
// → Compiler 가 거부.
|
||||
|
||||
// ✅
|
||||
useEffect(() => {
|
||||
localStorage.setItem('x', 'y');
|
||||
}, []);
|
||||
```
|
||||
|
||||
### Conditional hook (안 됨)
|
||||
```tsx
|
||||
// ❌
|
||||
if (cond) {
|
||||
useState(0); // hook 가 conditional
|
||||
}
|
||||
|
||||
// ✅
|
||||
const [x, setX] = useState(cond ? 0 : null);
|
||||
```
|
||||
|
||||
### Closure stale (자동 fix)
|
||||
```tsx
|
||||
// 옛 (stale)
|
||||
function Component({ value }) {
|
||||
const onClick = useCallback(() => log(value), []); // dep 빠짐 = stale
|
||||
return <button onClick={onClick} />;
|
||||
}
|
||||
|
||||
// Compiler:
|
||||
const onClick = () => log(value); // 자동 dep tracking.
|
||||
```
|
||||
|
||||
→ Compiler 가 stale closure bug 감소.
|
||||
|
||||
### Not a silver bullet
|
||||
```
|
||||
Compiler 가 안 fix:
|
||||
- Logic bug (correct 동작 X).
|
||||
- Network / async race.
|
||||
- DOM manipulation 직접.
|
||||
- Effect 의 timing.
|
||||
|
||||
→ Quality 가 매우 ↑ but not magic.
|
||||
```
|
||||
|
||||
### Compatibility
|
||||
```
|
||||
React 18: 부분 (experimental).
|
||||
React 19+: stable.
|
||||
React Native 0.75+: 가능.
|
||||
```
|
||||
|
||||
### Production 사용
|
||||
- **Meta** (FB): 큰 internal.
|
||||
- **Anthropic Claude**: 모든 React 가 compiled.
|
||||
- **Vercel / Next**: native.
|
||||
- **다양 modern app**.
|
||||
|
||||
### Migration
|
||||
```
|
||||
1. Existing app (no compiler).
|
||||
2. ESLint react-compiler 활성.
|
||||
3. Violation fix (1-2 일).
|
||||
4. Compiler 활성.
|
||||
5. Manual memo 점차 제거.
|
||||
```
|
||||
|
||||
### Bundle size
|
||||
```
|
||||
Compiler: 0 (build-time).
|
||||
useMemoCache: 작은 runtime addition.
|
||||
React 19 자체: 약간 작음.
|
||||
```
|
||||
|
||||
### Common violation
|
||||
```
|
||||
- Mutation in render.
|
||||
- 외부 변수 변경.
|
||||
- Hook 가 conditional.
|
||||
- Side effect render 중.
|
||||
- Function 안 hook 호출.
|
||||
```
|
||||
|
||||
→ ESLint 가 모두 catch.
|
||||
|
||||
### Testing
|
||||
```tsx
|
||||
// React Testing Library
|
||||
test('counter', () => {
|
||||
const { getByText } = render(<Counter />);
|
||||
fireEvent.click(getByText('+'));
|
||||
expect(getByText('1')).toBeInTheDocument();
|
||||
});
|
||||
```
|
||||
|
||||
→ Compiler 가 transparent. Test 가 same.
|
||||
|
||||
### Devtools
|
||||
```
|
||||
React DevTools 가 compiled component:
|
||||
- "Memo" badge.
|
||||
- Cache hit / miss visible.
|
||||
|
||||
→ Profiler 가 도움.
|
||||
```
|
||||
|
||||
### Profiler
|
||||
```tsx
|
||||
import { Profiler } from 'react';
|
||||
|
||||
<Profiler id="App" onRender={(...) => log(...)}>
|
||||
<App />
|
||||
</Profiler>
|
||||
```
|
||||
|
||||
### Future
|
||||
```
|
||||
- Compiler stable (현재).
|
||||
- Compiler 가 RSC 도 optimize.
|
||||
- React Native 도.
|
||||
- "Plain code, compiler 가 fast" 가 standard.
|
||||
```
|
||||
|
||||
### vs Solid / Svelte 5 (signal)
|
||||
```
|
||||
React Compiler: VDOM + memo.
|
||||
Solid: signal (no VDOM diff).
|
||||
Svelte 5: rune (signal).
|
||||
|
||||
→ React 가 backwards compatible.
|
||||
Solid / Svelte 가 더 빠름 (specific).
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준
|
||||
| 상황 | 추천 |
|
||||
|---|---|
|
||||
| New React app | React 19 + Compiler |
|
||||
| Existing | Gradual migrate |
|
||||
| Specific opt-out | "use no memo" |
|
||||
| Library author | Compile by default |
|
||||
| Manual control | useMemo (rare) |
|
||||
| 큰 perf gap | Profile + Million.js |
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Manual memo + compiler**: redundant.
|
||||
- **Mutation in render**: violation.
|
||||
- **ESLint 무시**: silent break.
|
||||
- **Compiler 가 fix all**: profile.
|
||||
- **"use no memo" 모든 file**: pointless.
|
||||
- **Side effect render 중**: violation.
|
||||
|
||||
## 🤖 LLM 활용 힌트
|
||||
- React Compiler = automatic memo (React 19+).
|
||||
- ESLint react-compiler 가 violation catch.
|
||||
- Manual useMemo 가 obsolete.
|
||||
- Plain code → compiler 가 optimize.
|
||||
|
||||
## 🔗 관련 문서
|
||||
- [[Frontend_Million_Optimization]]
|
||||
- [[React_useMemo_When_Not_To]]
|
||||
- [[React_Rendering_Optimization]]
|
||||
Reference in New Issue
Block a user